Skip to content

Instantly share code, notes, and snippets.

@Luiz-Monad
Created November 5, 2021 23:14
Show Gist options
  • Save Luiz-Monad/5d8ae514745b2da49ec50853c3b90368 to your computer and use it in GitHub Desktop.
Save Luiz-Monad/5d8ae514745b2da49ec50853c3b90368 to your computer and use it in GitHub Desktop.
Recursive type lift in typescript
type FLeaf<T, N> = { leaf: T; name: N }
type FNode<T, N> = { node: T; name: N }
type Fold<T> = {
[K in keyof T & string]:
Lift<T[K], K>
}[keyof T & string];
type Lift<T, K> =
T extends Array<any> ? FLeaf<T, K> :
T extends object ? FNode<T, K> :
FLeaf<T, K>
type RecurseN<T> =
T extends FLeaf<any, any> ? T :
T extends FNode<infer ST, infer SK> ? FNode<RecurseN<ST>, SK> :
RecurseN<Fold<T>>
type Select<T, N> =
T extends { node: infer K; name: N } ? K :
T extends { leaf: infer K; name: N } ? K : never;
type Test = RecurseN<A>
type S0 = Select<Test, 'a'>
type S1 = Select<S0, 'b'>
type S2 = Select<S1, 'c'>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment