Skip to content

Instantly share code, notes, and snippets.

@reverofevil
Created December 18, 2021 01:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reverofevil/adbf0ac4cb99a913419775120d48482d to your computer and use it in GitHub Desktop.
Save reverofevil/adbf0ac4cb99a913419775120d48482d to your computer and use it in GitHub Desktop.
type IfEquals<X, Y, A, B> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? A : B;
type ReadonlyKeys<U, T = { [K in keyof U]-?: U[K] }> = {
[P in keyof T]: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, never, P>
}[keyof T];
type Full<T, R = ReadonlyKeys<T>> = {
-readonly [K in keyof T]-?: {
type: T[K],
optional: T extends Record<K, any> ? false : true,
readonly: K extends R ? true : false,
}
}
type Unfuck<T> = T extends infer R ? {[K in keyof R]: R[K]} : never;
type Test<T> = {a?: any} extends { [K in keyof T as 'a']: T[K] } ? 'bar' : 'foo'
type First<U> = {
[K in keyof U as Test<Partial<U> & Record<K, U[K]>>]: K
} extends {foo: infer R} ? R : 1
type DescribeIter<T, R = First<T>> = R extends string
? T extends Record<R, any>
? [
Unfuck<{name: R} & T[R]>,
...DescribeIter<Unfuck<Omit<T, R>>>
]
: never
: []
type Describe<T> = DescribeIter<Full<T>>
type R = Describe<{
a?: number,
b: string,
readonly c: boolean,
readonly d?: 'e',
}>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment