getOneofValue typing is incorrect
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.
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.