Improve path.get typings with TS template literal types (#13588)
This commit is contained in:
parent
0a4b1b339c
commit
d45ad500e7
@ -320,6 +320,44 @@ export function getAllPrevSiblings(this: NodePath): NodePath[] {
|
|||||||
return siblings;
|
return siblings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert "1" to 1 (string index to number index)
|
||||||
|
type MaybeToIndex<T extends string> = T extends `${bigint}` ? number : T;
|
||||||
|
|
||||||
|
type Pattern<Obj extends string, Prop extends string> = `${Obj}.${Prop}`;
|
||||||
|
|
||||||
|
// split "body.body.1" to ["body", "body", 1]
|
||||||
|
type Split<P extends string> = P extends Pattern<infer O, infer U>
|
||||||
|
? [MaybeToIndex<O>, ...Split<U>]
|
||||||
|
: [MaybeToIndex<P>];
|
||||||
|
|
||||||
|
// get all K with Node[K] is t.Node | t.Node[]
|
||||||
|
type NodeKeyOf<Node extends t.Node | t.Node[]> = keyof Pick<
|
||||||
|
Node,
|
||||||
|
{
|
||||||
|
[Key in keyof Node]-?: Node[Key] extends t.Node | t.Node[] ? Key : never;
|
||||||
|
}[keyof Node]
|
||||||
|
>;
|
||||||
|
|
||||||
|
// traverse the Node with tuple path ["body", "body", 1]
|
||||||
|
// Path should be created with Split
|
||||||
|
type Trav<
|
||||||
|
Node extends t.Node | t.Node[],
|
||||||
|
Path extends unknown[],
|
||||||
|
> = Path extends [infer K, ...infer R]
|
||||||
|
? K extends NodeKeyOf<Node>
|
||||||
|
? R extends []
|
||||||
|
? Node[K]
|
||||||
|
: // @ts-expect-error ignore since TS is not smart enough
|
||||||
|
Trav<Node[K], R>
|
||||||
|
: never
|
||||||
|
: never;
|
||||||
|
|
||||||
|
type ToNodePath<T> = T extends Array<t.Node | null | undefined>
|
||||||
|
? Array<NodePath<T[number]>>
|
||||||
|
: T extends t.Node | null | undefined
|
||||||
|
? NodePath<T>
|
||||||
|
: never;
|
||||||
|
|
||||||
function get<T extends t.Node, K extends keyof T>(
|
function get<T extends t.Node, K extends keyof T>(
|
||||||
this: NodePath<T>,
|
this: NodePath<T>,
|
||||||
key: K,
|
key: K,
|
||||||
@ -330,6 +368,12 @@ function get<T extends t.Node, K extends keyof T>(
|
|||||||
? NodePath<T[K]>
|
? NodePath<T[K]>
|
||||||
: never;
|
: never;
|
||||||
|
|
||||||
|
function get<T extends t.Node, K extends string>(
|
||||||
|
this: NodePath<T>,
|
||||||
|
key: K,
|
||||||
|
context?: boolean | TraversalContext,
|
||||||
|
): ToNodePath<Trav<T, Split<K>>>;
|
||||||
|
|
||||||
function get<T extends t.Node>(
|
function get<T extends t.Node>(
|
||||||
this: NodePath<T>,
|
this: NodePath<T>,
|
||||||
key: string,
|
key: string,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user