Skip to content

PartialMessage<T> of message with oneof field requires that oneof field be non-partial #380

@jcready

Description

@jcready

Calling .create() on a MessageType instance allows partial oneof fields at runtime, but at compile-time they are required to be non-partial. TS Playground

// pulled from https://github.com/timostamm/protobuf-ts/blob/master/packages/runtime/src/message-type-contract.ts
export type PartialMessage<T extends object> = {
    [K in keyof T]?: PartialField<T[K]>
}; type PartialField<T> =
     T extends (Date | Uint8Array | bigint | boolean | string | number) ? T
   : T extends Array<infer U> ? Array<PartialField<U>>
   : T extends ReadonlyArray<infer U> ? ReadonlyArray<PartialField<U>>
   : T extends { oneofKind: string } ? T
   : T extends { oneofKind: undefined } ? T
   : T extends object ? PartialMessage<T>
   : T ;

// example
interface Bar {
    arr: number[];
    other?: number;
}

interface Foo {
    args: {
        oneofKind: "bar";
        bar: Bar;
    } | {
        oneofKind: undefined;
    }
}

function create(i: PartialMessage<Foo>) {}

create({
    args: {
        oneofKind: 'bar',
        bar: { // ts-2741: Property 'arr' is missing in type '{ other: number; }' but required in type 'Bar'.
            other: 1,
        }
    }
})

I don't think there's actually a way to get this working given the existing types. This is another instance where the updated oneof representation would make this trivial: : T extends { kind: string; value: infer U } ? { kind: T['kind']; value: PartialField<U> }.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions