-
Notifications
You must be signed in to change notification settings - Fork 391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
「重学TS 2.0 」TS 练习题第二十九题 #48
Comments
type indexSignature<T> = T extends `${infer H}[${infer M}][${infer R}]`
? [H, M, ...indexSignature<`[${R}]`>]
: T extends `${infer F}[${infer L}]`
? [F, L]
: [T];
type NonSpace<T extends string[]> = T extends [infer H, ...infer R]
? R extends string[]
? H extends ""
? [...NonSpace<R>]
: [H, ...NonSpace<R>]
: never
: T;
type ToPath<S extends string> = S extends `${infer H}.${infer R}`
? [...NonSpace<indexSignature<H>>, ...ToPath<R>]
: NonSpace<indexSignature<S>>;
type t1 = ToPath<"foo.bar.baz">; //=> ['foo', 'bar', 'baz']
type t2 = ToPath<"foo[0][2][3][4].bar[5][6].baz[12][13]">; //=> ['foo','0','2','3','4','bar','5','6','baz','12','13'] |
|
type Str2Tuple<S extends string> = S extends `${infer First}[${infer Second}]`
? [First, Second]
: [S];
type ToPath<S extends string> = S extends `${infer First}.${infer Rest}`
? [...Str2Tuple<First>, ...ToPath<Rest>]
: [S];
type T1 = ToPath<"foo.bar.baz">; //=> ['foo', 'bar', 'baz']
type T2 = ToPath<"foo[0].bar.baz">; //=> ['foo', '0', 'bar', 'baz'] |
感觉我这个方法有点僵硬, 完全就是字符串的替换, 把 type ToPath<T extends string, C extends string[] = []> =
T extends `${infer R1}[${infer R2}`
? ToPath<`${R1}.${R2}`>
: T extends `${infer R3}]${infer R4}`
? ToPath<`${R3}${R4}`>
: T extends `${infer R5}.${infer R6}`
? [R5, ...ToPath<R6, C>]
: [T]
// 测试用例
type t1 = ToPath<'foo.bar.baz'> //=> ['foo', 'bar', 'baz']
type t2 = ToPath<'foo[0].bar[1].baz[2].fff'> //=> ['foo', '0', 'bar', 'baz'] |
type ToPath<S extends string> =
S extends '' ? [] :
S extends `${infer A}[${infer B}]${infer C}` ? [...ToPath<A>, B, ...ToPath<C extends `.${infer D}` ? D : C>] : Split<S, '.'>
type T1 = ToPath<'foo.bar.baz'> //=> ['foo', 'bar', 'baz']
type T2 = ToPath<'foo[0].bar.baz'> //=> ['foo', '0', 'bar', 'baz']
type T3 = ToPath<'foo.bar[0].baz'> //=> ['foo', 'bar', '0', 'baz']
type T4 = ToPath<'foo.bar.baz[0]'> //=> ['foo', 'bar', 'baz', '0']
type T5 = ToPath<'baz[0]'> //=> ['baz', '0']
type T6 = ToPath<'[0].foo[1][3].bar[2]'> //=> ['0','foo','1','3','bar','2'] |
|
type ToPath<S extends string> = S extends `${infer A}.${infer B}`
? [...ToPath<A>, ...ToPath<B>]
: S extends `${infer A}[${infer B}]`
? [A, B]
: [S]
type T1 = ToPath<'foo.bar.baz'> //=> ['foo', 'bar', 'baz']
type T2 = ToPath<'foo[0].bar.baz'> //=> ['foo', '0', 'bar', 'baz'] 利用 infer 的一些小技巧,结合模板变量的用法。 |
|
type ToPath<S extends string> = S extends `${infer A}${"["}${infer C}`
? [A, ...ToPath<C>]
: S extends `${infer A}${"]"}${infer C}`
? [A, ...ToPath<C>]
: S extends `${infer A}${"."}${infer C}`
? (A extends ""
? [...ToPath<C>]
: [A, ...ToPath<C>])
: [S];
type T0 = ToPath<"foo.bar.baz">; //=> ['foo', 'bar', 'baz']
type T1 = ToPath<"foo[0].bar.baz">; //=> ['foo', '0', 'bar', 'baz'] |
type StrBrackets<S extends string> = S extends `${infer A}[${infer B}]`
? [A, B]
: [S];
type ToPath<S extends string> = S extends `${infer A}.${infer B}`
? [...StrBrackets<A>, ...ToPath<B>]
: [...StrBrackets<S>];
type toPath = ToPath<"foo.bar.baz">; //=> ['foo', 'bar', 'baz']
type toPath2 = ToPath<"foo[0].bar.baz">; //=> ['foo', '0', 'bar', 'baz'] |
|
type Split< type a = ToPath<'foo.bar.baz'>; |
type ToPath<S extends string, R extends string[] = []> = S extends `${infer Prev}.${infer Last}` ? Prev extends `${infer Key}[${infer Index}]` ? ToPath<Last, [...R, Key, Index]> : ToPath<Last, [...R, Prev]> : '' extends S ? R : [...R, S];
type A = ToPath<'foo.bar.baz'> //=> ['foo', 'bar', 'baz']
type B = ToPath<'foo[0].bar.baz'> //=> ['foo', '0', 'bar', 'baz'] |
type ToPath type TransferStr<T extends Array = []> = { type Result2 = Flat<TransferStr<ToPath<'foo[0].[0]bar.b[0]az'>>> //=> ["foo", "0", "0", "bar", "b", "0", "az"] |
type ToPath<S extends string> = S extends `${infer F}.${infer R}`
? [...ToPath<F>, ...ToPath<R>]
: S extends `${infer F}[${infer C}]${infer R}`
? [...ToPath<F>, ...ToPath<C>, ...ToPath<R>]
: S extends ""
? []
: [S]; |
可能是比较简洁好懂的写法了> 每次看到这种需要循环处理的题目第一反应是想到递归
|
|
type Split<
S extends string,
Delimiter extends string,
> = S extends `${infer F}${Delimiter}${infer Rest}`
? [F, ...Split<Rest, Delimiter>]
: S extends '' ? [] : [S];
type D<S> = S extends `${infer A}[${infer B}]` ? [A, ...Split<B, ']['>] : [S];
type C<T extends any[]> = T extends [infer F, ...infer Rest] ? [...D<F>, ...C<Rest>] : T;
type ToPath<S extends string> = C<Split<S, '.'>>;
type A = ToPath<'foo.bar.baz'> //=> ['foo', 'bar', 'baz']
type B = ToPath<'foo[1].bar[6][7][8].baz[12]'> //=> ["foo", "1", "bar", "6", "7", "8", "baz", "12"] |
type ArrayChangeTuple< type ToPath< |
type ToPath<S extends string> = S extends `${infer K}[${infer M}]${infer R2}` ? [K,...ToPath<`${M}${R2}`>] : S extends `${infer P}.${infer Rest}` ?
[P,...ToPath<Rest>] : [S]
type T1 = ToPath<'foo.bar.baz'> //=> ['foo', 'bar', 'baz']
type T2 = ToPath<'foo[0].bar.baz'> //=> ['foo', '0', 'bar', 'baz'] |
// 拆分
type Split<
S extends string,
Delimiter extends string,
> = S extends `${infer A}${Delimiter}${infer B}` ? [A, ...Split<B, Delimiter>] : [S]
// 将方括号内的类型拆分
type StrSplit<S extends string, R extends string[] = []> =
S extends `${infer A}[${infer B}]${infer C}` ? (C extends "" ? (A extends "" ? [...R, B] : [...R, A, B]) : A extends "" ? [...R, B, ...StrSplit<C, R>] : [...R, A, B, ...StrSplit<C, R>]) : [S]
// 拆分数组每一项
type Spliting<T extends string[], R extends string[] = []> =
T extends [infer FirstStr extends string, ...infer RestStrs extends string[]] ?
(RestStrs extends [] ? [...R, ...StrSplit<FirstStr, R>] : [...R, ...StrSplit<FirstStr, R>, ...Spliting<RestStrs, R>]) : R
type ToPath<S extends string> = Spliting<Split<S, '.'>>
type path1 = ToPath<'foo.bar.baz'> //=> ['foo', 'bar', 'baz']
type path2 = ToPath<'foo[0].bar.baz'> //=> ['foo', '0', 'bar', 'baz']
type path3 = ToPath<'x.b.c[2][2][3].e.f[2][3][4]'> // => ["x", "b", "c", "2", "2", "3", "e", "f", "2", "3", "4"] |
|
这个是正确的,评论区好多都有问题,遇到这种 |
type StrBrackets<S> = S extends `${infer A}[${infer B}]${infer C}`
? [...(A extends '' ? [] : [A]), B, ...StrBrackets<C>]
: (S extends '' ? [] : [S])
type ToPath<S> = S extends `${infer A}.${infer B}`
? [...StrBrackets<A>, ...ToPath<B>]
: StrBrackets<S>
type x = ToPath<'foo.bar.baz'> //=> ['foo', 'bar', 'baz']
type y = ToPath<'foo[0].bar.baz'> //=> ['foo', '0', 'bar', 'baz']
type z = ToPath<'foo[0][1].bar.baz'> //=> ['foo', '0', '1', 'bar', 'baz']
type T3 = ToPath<'fo[1]o[0].b.ar[2].b[3]a.z.'> // ["fo", "1", "o", "0", "b", "ar", "2", "b", "3", "a", "z"]
type path3 = ToPath<'x.b.c[2][2][3].e.f[2][3][4]'> // => ["x", "b", "c", "2", "2", "3", "e", "f", "2", "3", "4"]
|
实现一个
ToPath
工具类型,用于把属性访问(.
或[]
)路径转换为元组的形式。具体的使用示例如下所示:The text was updated successfully, but these errors were encountered: