目的
Github上的类型体操,让你写出更加优雅的TS类型定义,以及探寻TS中我们不熟悉的只是,让我们开始TS的类型挑战把~2022希望通过更文的方式来督促自己学习,每日三题,坚持日更不断~~
题目大纲
01. Medium Trim
题目要求
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<Trim<'str'>, 'str'>>,
Expect<Equal<Trim<' str'>, 'str'>>,
Expect<Equal<Trim<' str'>, 'str'>>,
Expect<Equal<Trim<'str '>, 'str'>>,
Expect<Equal<Trim<' str '>, 'str'>>,
Expect<Equal<Trim<' \n\t foo bar \t'>, 'foo bar'>>,
]
我的答案
type EmptyType = " " | "\t" | "\n";
type TL<S extends string> = S extends `${infer P}${infer K}`
? P extends " " | "\t" | "\n"
? TL<K>
: S
: never;
type TR<S extends string> = S extends `${infer P}${EmptyType}` ? TR<P> : S;
type Trim<S extends string> = TR<TL<S>>;
知识点
- trimRight 不能和 TL 写的一样, 因为这里的 P 和 K其实是贪婪的抓取,不会想象成从末尾开始取,所以这里要明确 extends 是不是末尾有 EmptyType
- 对某个想要 TS 识别的特殊结构,直接枚举出来就行
2. Medium Capitalize
题目要求
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<Capitalize1<'foobar'>, 'Foobar'>>,
Expect<Equal<Capitalize1<'FOOBAR'>, 'FOOBAR'>>,
Expect<Equal<Capitalize1<'foo bar'>, 'Foo bar'>>,
Expect<Equal<Capitalize1<''>, ''>>,
Expect<Equal<Capitalize1<'a'>, 'A'>>,
Expect<Equal<Capitalize1<'b'>, 'B'>>,
Expect<Equal<Capitalize1<'c'>, 'C'>>,
Expect<Equal<Capitalize1<'d'>, 'D'>>,
Expect<Equal<Capitalize1<'e'>, 'E'>>,
Expect<Equal<Capitalize1<'f'>, 'F'>>,
Expect<Equal<Capitalize1<'g'>, 'G'>>,
Expect<Equal<Capitalize1<'h'>, 'H'>>,
Expect<Equal<Capitalize1<'i'>, 'I'>>,
Expect<Equal<Capitalize1<'j'>, 'J'>>,
Expect<Equal<Capitalize1<'k'>, 'K'>>,
Expect<Equal<Capitalize1<'l'>, 'L'>>,
Expect<Equal<Capitalize1<'m'>, 'M'>>,
Expect<Equal<Capitalize1<'n'>, 'N'>>,
Expect<Equal<Capitalize1<'o'>, 'O'>>,
Expect<Equal<Capitalize1<'p'>, 'P'>>,
Expect<Equal<Capitalize1<'q'>, 'Q'>>,
Expect<Equal<Capitalize1<'r'>, 'R'>>,
Expect<Equal<Capitalize1<'s'>, 'S'>>,
Expect<Equal<Capitalize1<'t'>, 'T'>>,
Expect<Equal<Capitalize1<'u'>, 'U'>>,
Expect<Equal<Capitalize1<'v'>, 'V'>>,
Expect<Equal<Capitalize1<'w'>, 'W'>>,
Expect<Equal<Capitalize1<'x'>, 'X'>>,
Expect<Equal<Capitalize1<'y'>, 'Y'>>,
Expect<Equal<Capitalize1<'z'>, 'Z'>>,
]
我的解答
type CapMap = {
a: "A";
b: "B";
c: "C";
d: "D";
e: "E";
f: "F";
g: "G";
h: "H";
i: "I";
j: "J";
k: "K";
l: "L";
m: "M";
n: "N";
o: "O";
p: "P";
q: "Q";
r: "R";
s: "S";
t: "T";
u: "U";
v: "V";
w: "W";
x: "X";
y: "Y";
z: "Z";
};
type Capitalize1<S extends string> = S extends ""
? ""
: S extends `${infer P}${infer T}`
? P extends keyof CapMap
? `${CapMap[P]}${T}`
: S
: never;
知识点
- 字符串模版的推断
- keyof 的使用
3. Medium Replace
题目要求
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<Replace<'foobar', 'bar', 'foo'>, 'foofoo'>>,
Expect<Equal<Replace<'foobarbar', 'bar', 'foo'>, 'foofoobar'>>,
Expect<Equal<Replace<'foobarbar', '', 'foo'>, 'foobarbar'>>,
Expect<Equal<Replace<'foobarbar', 'bra', 'foo'>, 'foobarbar'>>,
Expect<Equal<Replace<'', '', ''>, ''>>,
]
我的解答
type Replace<
S extends string,
From extends string,
To extends string
> = From extends ""
? S
: S extends `${infer T}${From}${infer Z}`
? `${T}${To}${Z}`
: S;
知识点
- 字符串推断的类型可以是动态外部传入的
- 替换的时候,对应替换的值,也可以是直接通过字符串拼接的方式进行组合的