-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathindex.ts
63 lines (54 loc) · 1.64 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
declare const _brand: unique symbol;
type Brand<Type, Name = "DefaultName"> = Type & { [_brand]: Name };
type ParserError<T extends string> = Brand<T, "ParserError">;
type ParseVar<T> = T extends `${infer Name}:${infer Type}`
? { name: Name; type: Type }
: { name: T; type: "string" };
export type ExtractVars<T extends string> =
T extends `${string}{{${infer Prop}}}${infer Rest}`
? ParseVar<Prop> | ExtractVars<Rest>
: never;
type ToType<T> = T extends "string"
? string
: T extends "number"
? number
: never;
type VarRecord<
Str extends string,
Ev extends ExtractVars<any> = ExtractVars<Str>
> = {
[K in Ev["name"]]: ToType<Extract<Ev, { name: K }>["type"]>;
};
type GetMissingVars<
Str extends string,
Obj extends Record<string, string>
> = ExtractVars<Str>["name"] extends infer Vars
? Vars extends string
? {
[K in Vars]: unknown extends Obj[K] ? `Missing var '${K}'` : never;
}[Vars]
: never
: never;
type Interpolate<
Str extends string,
Obj extends VarRecord<Str>
> = GetMissingVars<Str, Obj> extends infer MissingVars
? [MissingVars] extends [never]
? Str extends `${infer Prev}{{${infer Prop}}}${infer Rest}`
? `${Prev}${Obj[ParseVar<Prop>["name"] & keyof Obj]}${Interpolate<
Rest,
Obj & VarRecord<Rest>
>}`
: Str
: ParserError<Extract<MissingVars, string>>
: never;
type Demo = Interpolate<
`My Name Is {{name:string}}, I'm {{age:number}} years old`,
{ name: "Anurag"; age: 22 }
>;
type DoesNotExists = Interpolate<
`My Name Is {{name}}, I'm {{wow_look_at_me}} years old`,
// @ts-expect-error
{ name: "Anurag"; age: "19" }
>;
export {};