-
Notifications
You must be signed in to change notification settings - Fork 349
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: virtual oneof property #1099
Comments
Hi @paskozdilar ! Just sanity checking, but have you seen our existing oneof handling, i.e.: https://github.com/stephenh/ts-proto?tab=readme-ov-file#oneof-handling And specifically the It outputs code like:
Which seems very similar to this request, but I can't 100% tell ... is there something about the |
Yes, it's very similar, but unfortunately the However, the problem with the default flat-representation of
The problems could be solved by the virtual property field that would contain the name of the set oneof property, e.g.: message Foo {
oneof either_field { string field_a = 1; string field_b = 2; }
} would generate the following: export interface Foo {
eitherField: 'fieldA' | 'fieldB' | undefined;
fieldA: string | undefined;
fieldB: string | undefined;
}
// we can now do this:
function fn(foo: Foo) {
switch (foo.eitherField) {
case 'fieldA':
const fieldA = foo[foo.eitherField] as typeof Foo[foo.eitherField];
// ... handle field a
case 'field_b':
const fieldB = foo[foo.eitherField] as typeof Foo[foo.eitherField];
// ... handle field b
default:
// compiler will fail here if we haven't exhausted all non-undefined cases
let _: undefined;
_ = args.eitherField;
}
} That wouldn't give complete type-safety, but would still increase convenience. In the current implementation of flat-fields, all oneofs have to be checked manually, and one has to look at the proto file itself to know which field belongs to which oneof. Additionally, if we had a true union as message type, we could avoid the typecasting ( export type Foo = {
eitherField: 'fieldA';
fieldA: string;
} | {
eitherField: 'fieldB';
fieldB: string;
} | {
eitherField: undefined;
}
// we can now do this:
function fn(foo: Foo) {
switch (foo.eitherField) {
case 'fieldA':
const fieldA = foo.fieldA; // typescript infers string automatically
const _ = foo.fieldB; // error: property "fieldB" doesn't exist on { eitherField: "fieldA", fieldA: string }
// ... handle field a
case 'fieldB':
const fieldB = foo.fieldB;
// ... handle field b
default:
// compiler will fail here if we haven't exhausted all non-undefined cases
let _: undefined;
_ = args.eitherField;
}
} |
The
protobuf.js
library provides an optiononeofs
for setting virtual oneof fields that contain name of the set property:Similar option already exists in the generated pbjs.d.ts files in integration tests, e.g. in
oneof-properties
:It would be ideal to have generated interface actually be a flat union type with a virtual parameter, so TypeScript can check for field existence based on virtual field value, but my naive attempt has caused combinatorial explosion of union types related to
Exact
andDeepPartial
which are too complicated for me to tackle at the moment.Having just a virtual parameter is a weaker - but still useful - feature.
I am planning to do the work once I get more comfortable with the codebase. Any pointers would be welcome :)
The text was updated successfully, but these errors were encountered: