Skip to content

Instantly share code, notes, and snippets.

@BlackHole1
Created March 13, 2020 06:47
Show Gist options
  • Save BlackHole1/5f8d138f5131f68d423fe83e09d60b64 to your computer and use it in GitHub Desktop.
Save BlackHole1/5f8d138f5131f68d423fe83e09d60b64 to your computer and use it in GitHub Desktop.
type ObjKeyof<T> = T extends object ? keyof T : never
type KeyofKeyof<T> = ObjKeyof<T> | { [K in keyof T]: ObjKeyof<T[K]> }[keyof T]
type StripNever<T> = Pick<T, { [K in keyof T]: [T[K]] extends [never] ? never : K }[keyof T]>;
type Lookup<T, K> = T extends any ? K extends keyof T ? T[K] : never : never
type SimpleFlatten<T> = T extends object ? StripNever<{ [K in KeyofKeyof<T>]:
Exclude<K extends keyof T ? T[K] : never, object> |
{ [P in keyof T]: Lookup<T[P], K> }[keyof T]
}> : T
type NestedFlatten<T> = SimpleFlatten<SimpleFlatten<
SimpleFlatten<SimpleFlatten<SimpleFlatten<T>>>>>;
interface SimpleFlattenTest {
a: { b: string, c: number },
meow: { b: number, d: boolean }
}
type S1 = SimpleFlatten<SimpleFlattenTest>; // { b: string | number, c: number, d: boolean }
type S2 = SimpleFlatten<{}>; // {}
// differs here:
type S3 = SimpleFlatten<boolean>; // boolean, not never
// differs here:
type S4 = SimpleFlatten<{ a: string }>; // {a: string}, not never
interface NestedFlattenTest {
a: { b: string, c: number },
meow: { b: number, d: boolean },
nested: {
ignored: { d: string },
taco: { c: string }
}
}
type N1 = NestedFlatten<NestedFlattenTest>; // {
// b: string | number, c: number | string, d: boolean | string }
type N2 = NestedFlatten<{}>; // {}
type N3 = NestedFlatten<boolean>; // boolean
type N4 = NestedFlatten<{ a: string }>; // {a: string}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment