protobuf-ts icon indicating copy to clipboard operation
protobuf-ts copied to clipboard

getOneofValue typing is incorrect

Open be9 opened this issue 3 years ago • 1 comments

hey Timo, I found a deficiency in typings around oneofs.

In a nutshell, getOneofValue typing works for oneofs with scalar values, but doesn't work when any option has a message value.

Here's the repro:

import { getOneofValue, isOneofGroup } from '@protobuf-ts/runtime';

type SimpleOneof =
    | { oneofKind: "a"; a: string; }
    | { oneofKind: "b"; b: number; }
    | { oneofKind: "c"; c: boolean; }
    | { oneofKind: undefined; };

// this works (similar to oneof.spec.ts)
function simpleTest(oneof: SimpleOneof): string | undefined {
    return getOneofValue(oneof, 'a');
}


interface Foo {
    foo: string;
}

interface Bar {
    bar: string;
}

// this type uses messages as oneof values
type FooBarOneof =
    | { oneofKind: "foo"; foo: Foo; }
    | { oneofKind: "bar"; bar: Bar; }
    | { oneofKind: undefined; };

function fooBarTest(oneof: FooBarOneof): void {
/*
Argument of type 'FooBarOneof' is not assignable to parameter of type 'UnknownOneofGroup'.
  Type '{ oneofKind: "foo"; foo: Foo; }' is not assignable to type 'UnknownOneofGroup'.
    Property 'foo' is incompatible with index signature.
      Type 'Foo' is not assignable to type 'UnknownScalar | UnknownMessage | undefined'.
        Type 'Foo' is not assignable to type 'UnknownMessage'.
          Index signature for type 'string' is missing in type 'Foo'.ts(2345)    
*/
    getOneofValue(oneof, 'foo');

    // what if we force oneof to be a `UnknownOneofGroup`? still doesn't work :(
    if (isOneofGroup(oneof)) {
        // Argument of type 'string' is not assignable to parameter of type 'never'.ts(2345)        
        getOneofValue(oneof, 'bar');
    }
}

(also available here https://github.com/be9/protobuf-ts-oneof-fail)

I don't know enough about TS conditional types, so couldn't fix it myself.

be9 avatar Aug 25 '22 05:08 be9

Thanks for the heads-up. Unfortunately, TypeScript doesn't seem to like the index signature. We are going to move to a different oneof representation in the next major (see https://github.com/timostamm/protobuf-ts/pull/262), so this helper function will probably not be necessary anymore. That doesn't mean this shouldn't be fixed, but with limited time available, this one probably doesn't get the highest priority.

timostamm avatar Aug 29 '22 19:08 timostamm