creditkarma / thrift-typescript

Generate TypeScript from Thrift IDL files
Apache License 2.0
155 stars 32 forks source link

Strict unions could be made simpler with a type helper #168

Open hayes opened 5 years ago

hayes commented 5 years ago

I'm not sure what this projects stance is on type helpers, but the output for strict unions is pretty verbose.

I am working on a project where we create interfaces very similar to the ones used by this project for strict unions. Our approach uses a type helper to create much smaller output for complex unions.

I'm not sure if this would be a good idea to adopt here, but thought I would share it in case you think it's useful:

We use the following type helpers:

export type UnionObject<T extends {}, Undefined = undefined> = {
  [K in keyof T]: Pick<T, K> & { [J in Exclude<keyof T, K>]?: Undefined }
}[keyof T];

export type UnionObjectWithType<T extends {}, Undefined = undefined> = {
  [K in keyof T]: Pick<T, K> & { [J in Exclude<keyof T, K>]?: Undefined } & { __type: K }
}[keyof T];

which could be used like:

type MyUnion = UnionObject<{
  foo: number;
  bar: string;
}>;

type MyUnionWithType = UnionObjectWithType<{
  foo: number;
  bar: string;
}>;

const x: MyUnion = {
  bar: '1232',
};

const y: MyUnion = {
  foo: 1232,
  bar: undefined,
};

const z: MyUnionWithType = {
  __type: 'foo',
  foo: 1232,
  bar: undefined,
};

/*
Type '{ foo: number; bar: string; }' is not assignable to type '(Pick<{ foo: number; bar: string; }, "foo"> & { bar?: undefined; }) | (Pick<{ foo: number; bar: string; }, "bar"> & { foo?: undefined; })'.
  Type '{ foo: number; bar: string; }' is not assignable to type 'Pick<{ foo: number; bar: string; }, "bar"> & { foo?: undefined; }'.
    Type '{ foo: number; bar: string; }' is not assignable to type '{ foo?: undefined; }'.
      Types of property 'foo' are incompatible.
        Type 'number' is not assignable to type 'undefined'.ts(2322)
*/
const error: MyUnion = {
  foo: 1232,
  bar: 'asd',
};