Created
June 11, 2023 01:22
-
-
Save schicks/1bee5b5690ad1c895628798f1cdd6701 to your computer and use it in GitHub Desktop.
selection types for graphql queries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Scalar = string | number | boolean | undefined | null | |
type ScalarsOf<T> = {[Key in keyof T]: T[Key] extends Scalar ? Key : never}[keyof T] | |
type ObjectsOf<T> = {[Key in keyof T]: T[Key] extends Scalar ? never : Key}[keyof T] | |
type Simplify<T> = T extends Function ? T : {[K in keyof T]: Simplify<T[K]>}; | |
type ValuableKeys<T> = {[Key in keyof T]: T[Key] extends never ? never : Key}[keyof T] | |
type Nevertheless<T> = T extends {} ? {[K in ValuableKeys<T>]: Nevertheless<T[K]>} : T | |
type CompleteSelector<T> = {[Key in ScalarsOf<T>]: true} & { | |
[Key in ObjectsOf<T>]: T[Key] extends (infer U)[] ? CompleteSelector<U> : CompleteSelector<T[Key]> | |
} | |
type Selector<S, T> = CompleteSelector<T> extends S ? S & {__resultType: SelectionResult<S, T>} : never // throw away invalid selectors | |
type Selected<S, T> = T extends Scalar | |
? T | |
: T extends (infer U)[] | |
? SelectionResult<S, U>[] | |
: SelectionResult<S, T> | |
type SelectionResult<S, T> = CompleteSelector<T> extends S ? { | |
[Key in keyof S]: Key extends keyof T | |
? Selected<S[Key], T[Key]> | |
: never // throw away impossible keys | |
} : never // throw away invalid selectors | |
const s = <T>() => <S>(s: S): Selector<S, T> => s as any | |
type Infer<S extends {__resultType: any}> = Simplify<S['__resultType']> | |
type User = { | |
id: string | |
org: Organization | |
} | |
type Organization = { | |
id: string | |
leader: User | |
second: User | |
members: User[] | |
} | |
type Query = { | |
getUser: User | |
} | |
const q = s<Query>() | |
const result = q({ | |
getUser: { | |
id: true, | |
org: { | |
leader: { | |
id: true | |
}, | |
second: { | |
id: true | |
}, | |
members: { | |
id: true | |
} | |
} | |
} | |
}) | |
type Result = Infer<typeof result> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment