Skip to content

Instantly share code, notes, and snippets.

@kamoshi
Created August 29, 2023 17:39
Show Gist options
  • Save kamoshi/d612a66ae482f91448681007a41deb14 to your computer and use it in GitHub Desktop.
Save kamoshi/d612a66ae482f91448681007a41deb14 to your computer and use it in GitHub Desktop.
Typecheck nested props
/**
* Extract nested type from interface or object type.
*
* Example usage:
* ```ts
* type result = CheckNested<["a", "b"], {a: {b: number}}>;
* ```
*/
type ExtractNestedType<
Props extends any[],
Dict extends object,
> =
Props extends []
? Dict :
Props extends [infer Last]
? Last extends keyof Dict
? Dict[Last]
: never :
Props extends [infer Head, ...infer Tail]
? Head extends keyof Dict
? Dict[Head] extends object
? ExtractNestedType<Tail, Dict[Head]>
: never
: never :
never;
type SubSplit<Props extends string> =
Props extends `${infer Prop}.${infer Rest}`
? [Prop, ...SubSplit<Rest>]
: [Props];
type Split<Props extends string> =
Props extends `${infer Prop}|${infer Rest}`
? [SubSplit<Prop>, ...Split<Rest>]
: [SubSplit<Props>];
type CheckPaths<
Dict extends object,
Paths extends any[],
> =
Paths extends [infer Head, ...infer Tail]
? Head extends any[]
? ExtractNestedType<Head, Dict> extends never
? never
: CheckPaths<Dict, Tail>
: never :
Dict;
type SatisfiesPaths<D, P> =
D extends object
? P extends string
? CheckPaths<D, Split<P>> extends never
? never
: D
: D
: D;
type test = SatisfiesPaths<{a: {b: 5}; c: number}, 'a.b'>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment