awesome-typescript
awesome-typescript copied to clipboard
「重学TS 2.0 」TS 练习题第九题
第九题
定义一个 JoinStrArray
工具类型,用于根据指定的 Separator
分隔符,对字符串数组类型进行拼接。具体的使用示例如下所示:
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> = // 你的实现代码
// 测试用例
type Names = ["Sem", "Lolo", "Kaquko"]
type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko"
type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko"
type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
请在下面评论你的答案
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> =
Arr extends [infer El,...infer Rest] ?
Rest extends string[] ?
El extends string ?
Result extends "" ?
JoinStrArray<Rest, Separator,`${El}`> :
JoinStrArray<Rest, Separator,`${Result}${Separator}${El}`> :
`${Result}` :
`${Result}` :
`${Result}`
type Names = ["Sem", "Lolo", "Kaquko"]
type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko"
type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko"
type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
结果看起来没问题,但好像有报错
type JoinStrArray<
Arr extends string[],
Separator extends string
> = Arr extends [infer A, ...infer B]
? `${A extends string ? A : ''}${B extends [string, ...string[]]
? `${Separator}${JoinStrArray<B, Separator>}`
: ''}`
: '';
type JoinStrArray<Arr extends string[], Separator extends string> = Arr extends [infer El, ...infer Res]
? `${Arr[0]}${Res extends string[]
? Res[0] extends string
? `${Separator}${JoinStrArray<Res, Separator>}`
: ""
: ""}`
: ""
// 测试用例
type Names = ["Sem", "Lolo", "Kaquko"]
type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko"
type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko"
type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
// 定义一个 JoinStrArray 工具类型,用于根据指定的 Separator 分隔符,对字符串数组类型进行拼接。具体的使用示例如下所示:
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> = Arr extends [infer A, ...infer B]
? Result extends ""
? JoinStrArray<B, Separator, A>
: JoinStrArray<B, Separator, `${Result}${Separator}${A}`>
: Result;
// 测试用例
type Names = ["Sem", "Lolo", "Kaquko"]
type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko"
type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko"
type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
这个题需要明白 类型映射的代码里可以用 js 里模板变量的用法。之后就是extends 配合 infer 从数组中提取类型出来。
type ArrayShift<T extends string[]> = T extends [first: string, ...rest: infer R] ? R : [];
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> = {
2: Result,
1: JoinStrArray<ArrayShift<Arr>, Separator, `${Result}${Arr[0]}`>
0: JoinStrArray<ArrayShift<Arr>, Separator, `${Result}${Arr[0]}${Separator}`>
}[Arr extends [first: string, second: string, ...rest: string[]] ? 0 : Arr extends [] ? 2 : 1]
// 测试用例
type Names = ["Sem", "Lolo", "Kaquko"]
type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko"
type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko"
type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
type JoinStrArray<Arr extends string[],Separator extends string> = Arr extends [infer first, ...infer rest]
? ${first extends string ? first : ""}${rest extends [string, ...string[]] ?
${Separator}${JoinStrArray<rest, Separator>} : ""}
: ""; // 你的实现代码
// 测试用例 type Names = ["Sem", "Lolo", "Kaquko"]; type NamesComma = JoinStrArray<Names, ",">; // "Sem,Lolo,Kaquko" type NamesSpace = JoinStrArray<Names, " ">; // "Sem Lolo Kaquko" type NamesStars = JoinStrArray<Names, "⭐️">; // "Sem⭐️Lolo⭐️Kaquko"
type JoinStrArray<Arr, Separator extends string, Result extends string = ""> = (
Arr extends [infer L, ...infer R] ? L extends string ? JoinStrArray<R, Separator, ${Result}${Result extends '' ? '' : Separator}${L}
> : never : Result
)
// 测试用例 type Names = ["Sem", "Lolo", "Kaquko"] type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko" type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko" type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
type JoinStrArray<Arr, Separator extends string, Result extends string = ""> = (
Arr extends [infer L, ...infer R] ? L extends string ? JoinStrArray<R, Separator, ${Result}${Result extends '' ? '' : Separator}${L}
> : never : Result
)
// 测试用例 type Names = ["Sem", "Lolo", "Kaquko"] type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko" type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko" type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
type JoinStrArray<A extends string[], Separator extends string> = A extends [infer B, ...infer C] ? B extends string ? C extends [string, ...string[]] ? `${B}${Separator}${JoinStrArray<C, Separator>}` : B : '' : '';
type JoinStrArray<A extends string[], Separator extends string> =
A extends [infer One, ...infer Others]
? One extends string
? Others extends string[]
? `${One}${Separator}${JoinStrArray<Others, Separator>}`
: `${One}`
: ''
: A extends [infer OnlyOne]
? OnlyOne extends string
? `${OnlyOne}`
: ''
: '';
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> =
Arr['length'] extends 0
? Result
: Arr extends [infer First, ...infer Rest]
? First extends string
? Rest extends string[]
? Rest['length'] extends 0
? JoinStrArray<Rest, Separator, `${Result}${First}`>
: JoinStrArray<Rest, Separator, `${Result}${First}${Separator}`>
: ''
: ''
: ''
// 测试用例
type Names = ["Sem", "Lolo", "Kaquko"]
type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko"
type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko"
type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
type JoinStrArray<
Arr extends string[],
Separator extends string,
Result extends string = ""
> = Arr extends [infer F, ...infer R]
? R extends string[]
? F extends string
? Result extends ""
? JoinStrArray<R, Separator, F>
: JoinStrArray<R, Separator, `${Result}${Separator}${F}`>
: Result
: Result
: Result;
求大佬帮忙每步的意思解释一下吧,小弟着实是有点不懂了
相当于是使用infer递归提取了rest参数, 然后再递归执行type
求大佬帮忙每步的意思解释一下吧,小弟着实是有点不懂了
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> =
// (1)Arr是否约束于[] 真就执行(2)
Arr extends [infer El, ...infer Rest] ?
// (2)Rest是否约束于string[] // 为真执行(3)
Rest extends string[] ?
// (3)El是否约束于string // 为真执行(4)
El extends string ?
// (4)Result是否约束为""
Result extends "" ?
// (4)为真,递归调用JoinStrArray<Rest = Arr, Separator, `${El}` == Result>
JoinStrArray<Rest, Separator, `${El}`> : // JoinStrArray<["Lolo","kaquko"], ",", "Sem"> 第一次递归调用 Result extends "" 为false
JoinStrArray<Rest, Separator, `${Result}${Separator}${El}`> : // JoinStrArray<["kaquko"], "," ,"Sem, Lolo">
`${Result}` :
`${Result}` :
`${Result}`
type Names = ["Sem", "Lolo", "Kaquko"]
type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko"
type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko"
type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
// 定义一个 JoinStrArray 工具类型,用于根据指定的 Separator 分隔符,对字符串数组类型进行拼接
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> =
// (1)Arr是否约束于[]
Arr extends [infer El, ...infer Rest] ?
// (2)Rest是否约束于string[]
Rest extends string[] ?
// (3)El是否约束于string
El extends string ?
// (4)Result是否约束为""
Result extends "" ?
// (4)为真,递归调用JoinStrArray<Rest = Arr, Separator, `${El}` == Result>
// JoinStrArray<["Lolo","kaquko"], ",", "Sem"> 第一次递归调用后Result extends "" 为false
JoinStrArray<Rest, Separator, `${El}`> :
// JoinStrArray<["kaquko"], "," ,"Sem,Lolo"> 再次调用
JoinStrArray<Rest, Separator, `${Result}${Separator}${El}`> :
`${Result}` :
`${Result}` :
`${Result}`
type Names = ["Sem", "Lolo", "Kaquko"]
type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko"
type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko"
type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"``
type RemoveFirstChar<T> = T extends ${string}${infer R}
? R:T;
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> = Arr extends [infer F, ...infer Rest] ? JoinStrArray<Rest,Separator,${Result}${Separator}${F&string}
>: RemoveFirstChar<Result>;// 你的实现代码
// 测试用例 type Names = ["Sem", "Lolo", "Kaquko"] type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko" type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko" type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> =
Arr extends [infer First, ...infer Rest] ?
First extends string ?
Rest extends [string, ...string[]] ?
JoinStrArray<Rest, Separator, `${Result}${First}${Separator}`>
:
`${Result}${First}`
:
`${Result}`
:
`${Result}`
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> =
Arr extends [infer First, ...infer Rest]
? JoinStrArray<Rest, Separator, ${Result}${First & string}${Separator}
> : Result
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> = Arr extends [infer El,...infer Rest] ? Rest extends string[] ? El extends string ? Result extends "" ? JoinStrArray<Rest, Separator,`${El}`> : JoinStrArray<Rest, Separator,`${Result}${Separator}${El}`> : `${Result}` : `${Result}` : `${Result}` type Names = ["Sem", "Lolo", "Kaquko"] type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko" type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko" type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
可以简化成
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> = Arr extends [infer El extends string, ...infer Rest extends string[]]
? Result extends ""
? JoinStrArray<Rest, Separator, `${El}`>
: JoinStrArray<Rest, Separator, `${Result}${Separator}${El}`>
: `${Result}`
type RemoveFirstItem<T extends string[]> = T extends [string, ... infer rest] ? rest : [];
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> =
Arr extends [] ? '' :
Arr extends [string] ?
${Result}${Result extends "" ? "" : Separator}${Arr[0]}
: ${Result}${JoinStrArray<RemoveFirstItem<Arr>, Separator,
${Result}${Result extends "" ? "" : Separator}${Arr[0]}>}
没看懂,Result是什么?为啥定义了一个Result但是没传进去
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> =
Arr extends [infer El,...infer Rest] ? //一层判断,若true则执行第二层判断。否则执行结果1
Rest extends string[] ? //二层判断,若true则执行第三层判断。否则执行结果2
El extends string ? //三层判断,若true则执行第四层判断。否则执行结果3
Result extends "" ? //四层判断,若true则执行结果5。否则执行结果4
JoinStrArray<Rest, Separator,`${El}`> : //结果5
JoinStrArray<Rest, Separator,`${Result}${Separator}${El}`> : //结果4
`${Result}` : //结果3
`${Result}` : //结果2
`${Result}` //结果1
//上面的判断把每组三元表达式画个括号层次就清楚了
//一二三层判断是为了判断递归中是否还有非空数组传进来,有就继续拼接,没有则返回上回拼接结果
//结果5为首次递归,传递数组第一个元素作为拼接结果
//结果4为非首次递归,将当前数组第一个元素和上次拼接结果进行拼接并传递给下回
type Names = ["Sem", "Lolo", "Kaquko"]
type NamesComma = JoinStrArray<Names, ","> // "Sem,Lolo,Kaquko"
type NamesSpace = JoinStrArray<Names, " "> // "Sem Lolo Kaquko"
type NamesStars = JoinStrArray<Names, "⭐️"> // "Sem⭐️Lolo⭐️Kaquko"
type JoinStrArray<Arr extends string[], Separator extends string, Result extends string = ""> =
Arr extends [infer El,...infer Rest]
? Rest extends string[]
? El extends string
? Result extends ""
? JoinStrArray<Rest, Separator,`${El}`>
: JoinStrArray<Rest, Separator,`${Result}${Separator}${El}`>
:`${Result}`
: `${Result}`
: `${Result}`
这个答案我看了半天,调了一下缩进终于看懂了。论缩进的重要性......
//没看懂那个Result是干嘛的
type JoinStrArray<
Arr extends string[],
Separator extends string,
> = Arr extends [infer First extends string, ...infer Rest extends string[]]
? `${First}${Separator}${JoinStrArray<Rest, Separator>}`
: "";