Open brandonryan opened 2 years ago
Updated version that allows for number indexed types (like array)
type TakeProp<T extends string> = T extends `${infer Prop}/${string}` ? Prop : never
type TakeRest<T extends string> = T extends `${string}/${infer Rest}` ? Rest : T
export type PathExtract<Value, Path extends string> =
TakeProp<Path> extends never ? //if path type is not a path, get the prop from Value
Path extends `${number}` ? //if we are dealing with a number index
number extends keyof Value ? Value[number] : unknown
: Path extends keyof Value ? Value[Path] : unknown //otherwise just regular prop get
: TakeProp<Path> extends `${number}` ? //try to see if prop is a number
number extends keyof Value ?
PathExtract<Value[number], TakeRest<Path>>
: unknown
: TakeProp<Path> extends keyof Value ? //check if prop is in value
PathExtract<Value[TakeProp<Path>], TakeRest<Path>> //recurse
: unknown //failure
Finalized version. This one can handle decoding as well. Also cleaned up the types
//This is a big utility type to let us path walk a type with a string
export type SplitPath<T extends string> = T extends `${infer Prop}/${infer Rest}` ? [Prop, Rest] : [unknown, T]
//Deal with json pointer encoding
export type Decode<T extends string> =
T extends `${infer A}~0${infer B}` ? `${Decode<A>}~${Decode<B>}` :
T extends `${infer A}~1${infer B}` ? `${Decode<A>}/${Decode<B>}` :
T
export type ExtractProp<Value, Prop extends string> =
//try to see if prop is a number
Prop extends `${number}` ?
number extends keyof Value ? Value[number] :
unknown :
//check if prop is in value
Decode<Prop> extends keyof Value ? Value[Decode<Prop>] : unknown
export type PathExtract<Value, Path extends string> =
Extract<Value, SplitPath<Path>[0], SplitPath<Path>[1]>
export type Extract<Value, Prop, Rest extends string> =
Prop extends string ? PathExtract<ExtractProp<Value, Prop>, Rest> :
ExtractProp<Value, Rest>
amazing job! so we have template literals now in TS? been waiting for soo long!
I made this type because I wanted a type safe way to pull properties from an object via a path, and I thought it might be useful to this library. I chose to make any properties not found in the object never, but you could use unknown to keep current functionality if you wanted. Just thought I'd share.
This currently does not cover ~0 and ~1 but i think with a little more work that could be figured out.