目的
Github上的类型体操,让你写出更加优雅的TS类型定义,以及探寻TS中我们不熟悉的只是,让我们开始TS的类型挑战把~2022希望通过更文的方式来督促自己学习,每日三题,坚持日更不断~~
题目大纲
01. CamelCase
题目要求
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<CamelCase<'foo-bar-baz'>, 'fooBarBaz'>>,
Expect<Equal<CamelCase<'foo-Bar-Baz'>, 'foo-Bar-Baz'>>,
Expect<Equal<CamelCase<'foo-Bar-baz'>, 'foo-BarBaz'>>,
Expect<Equal<CamelCase<'foo-bar'>, 'fooBar'>>,
Expect<Equal<CamelCase<'foo_bar'>, 'foo_bar'>>,
Expect<Equal<CamelCase<'foo--bar----baz'>, 'foo-Bar---Baz'>>,
Expect<Equal<CamelCase<'a-b-c'>, 'aBC'>>,
Expect<Equal<CamelCase<'a-b-c-'>, 'aBC-'>>,
Expect<Equal<CamelCase<'ABC'>, 'ABC'>>,
Expect<Equal<CamelCase<'-'>, '-'>>,
Expect<Equal<CamelCase<''>, ''>>,
Expect<Equal<CamelCase<'😎'>, '😎'>>,
]
我的答案
type isNever<T> = (() => T) extends () => never ? true : false;
type Letter = {
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 CamelCase<
S extends string,
F extends any = never,
R extends string = ""
> = S extends `${infer T}${infer P}`
? isNever<F> extends false
? T extends Letter[keyof Letter]
? CamelCase<`${P}`, never, `${R}-${T}`>
: T extends keyof Letter
? CamelCase<`${P}`, never, `${R}${Letter[T]}`>
: CamelCase<P, F, `${R}${T}`>
: T extends keyof Letter
? CamelCase<P, never, `${R}${T}`>
: T extends "-"
? P extends ""
? `${R}-`
: CamelCase<P, false, `${R}`>
: CamelCase<P, F, `${R}${T}`>
: R;
知识点
- 把对应特殊的 case 用 extends 判断出来,再用递归生成类型就可以
2. Medium KebabCase
题目要求
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<KebabCase<'FooBarBaz'>, 'foo-bar-baz'>>,
Expect<Equal<KebabCase<'fooBarBaz'>, 'foo-bar-baz'>>,
Expect<Equal<KebabCase<'foo-bar'>, 'foo-bar'>>,
Expect<Equal<KebabCase<'foo_bar'>, 'foo_bar'>>,
Expect<Equal<KebabCase<'Foo-Bar'>, 'foo--bar'>>,
Expect<Equal<KebabCase<'ABC'>, 'a-b-c'>>,
Expect<Equal<KebabCase<'-'>, '-'>>,
Expect<Equal<KebabCase<''>, ''>>,
Expect<Equal<KebabCase<'😎'>, '😎'>>,
]
我的解答
type KebabCase<
S extends string,
R extends string = ""
> = S extends `${infer D}${infer P}`
? D extends Letter[keyof Letter]
? KebabCase<
P,
R extends "" ? `${Uncapitalize<D>}` : `${R}-${Uncapitalize<D>}`
>
: KebabCase<P, `${R}${D}`>
: R;
知识点
- 递归和 infer 的使用
3. Medium Diff
题目要求
import { Equal, Expect } from '@type-challenges/utils'
type Foo = {
name: string
age: string
}
type Bar = {
name: string
age: string
gender: number
}
type cases = [
Expect<Equal<Diff<Foo, Bar>, { gender: number }>>,
Expect<Equal<Diff<Bar,Foo>, { gender: number }>>
]
我的解答
type Diff<
O,
O1,
K1 extends keyof O = keyof O,
K2 extends keyof O1 = keyof O1,
R = {
[K in Exclude<K1, K2>]: O[K];
} & {
[K in Exclude<K2, K1>]: O1[K];
}
> = {
[K in keyof R]: R[K];
};
知识点
Exclude和对象合并的写法