@gqlts/runtime
Version:
Gqlts runtime client
91 lines (77 loc) • 2.77 kB
text/typescript
//////////////////////////////////////////////////
// SOME THINGS TO KNOW BEFORE DIVING IN
/*
0. DST is the request type, SRC is the response type
1. FieldsSelection uses an object because currently is impossible to make recursive types
2. FieldsSelection is a recursive type that makes a type based on request type and fields
3. HandleObject handles object types
4. Handle__scalar adds all scalar properties excluding non-scalar props
*/
export type FieldsSelection<SRC extends Anify<DST> | undefined, DST> = {
tuple: DST extends Nil ? never : DST extends readonly [any, infer PAYLOAD] ? FieldsSelection<SRC, PAYLOAD> : never;
scalar: SRC;
union: Handle__isUnion<SRC, DST>;
object: HandleObject<SRC, DST>;
array: SRC extends Nil ? never : SRC extends (infer T)[] ? Array<FieldsSelection<T, DST>> : never;
__scalar: Handle__scalar<SRC, DST>;
never: never;
}[DST extends Nil
? 'never'
: SRC extends Nil
? 'never'
: DST extends readonly [any, any]
? 'tuple'
: DST extends false | 0
? 'never'
: SRC extends Scalar
? 'scalar'
: SRC extends any[]
? 'array'
: SRC extends { __isUnion?: any }
? 'union'
: DST extends { __scalar?: any }
? '__scalar'
: DST extends {}
? 'object'
: 'never'];
type HandleObject<SRC extends Anify<DST>, DST> = SRC extends Nil
? never
: Pick<
{
// using keyof SRC to maintain ?: relations of SRC type
[Key in keyof SRC]: Key extends keyof DST
? FieldsSelection<NonNullable<SRC[Key]>, NonNullable<DST[Key]>>
: SRC[Key];
},
Exclude<keyof DST, FieldsToRemove>
// {
// // remove falsy values
// [Key in keyof DST]: DST[Key] extends false | 0 ? never : Key
// }[keyof DST]
>;
type Handle__scalar<SRC extends Anify<DST>, DST> = SRC extends Nil
? never
: Pick<
// continue processing fields that are in DST, directly pass SRC type if not in DST
{
[Key in keyof SRC]: Key extends keyof DST ? FieldsSelection<SRC[Key], DST[Key]> : SRC[Key];
},
// remove fields that are not scalars or are not in DST
{
[Key in keyof SRC]: SRC[Key] extends Nil
? never
: Key extends FieldsToRemove
? never
: SRC[Key] extends Scalar
? Key
: Key extends keyof DST
? Key
: never;
}[keyof SRC]
>;
// TODO response union types are very dumb
type Handle__isUnion<SRC extends Anify<DST>, DST> = SRC extends Nil ? never : Omit<SRC, FieldsToRemove>; // just return the union type
type Scalar = string | number | Date | boolean | null | undefined;
type Anify<T> = { [P in keyof T]?: any };
type FieldsToRemove = '__isUnion' | '__scalar' | '__name';
type Nil = undefined | null;