实战二
KebabCaseToCamelCase
实现 aaa-bbb-ccc
=> aaaBbbCcc
思路
根据 -
拆分, 然后 Capitalize
每一部分
CamelCaseToKebabCase
实现 aaaBbbCcc
=> aaa-bbb-ccc
思路
没有 -
作为标志, 但是我们可以 判断 大小写
First extends Lowercase<First>
不是我们要找的大写字母 所以 不用先 拼接 -
找到大写字母, 记得改成小写
Chunk
实现对数组的 分组
比如 [1, 2, 3, 4 ,5], 2
=> [[1, 2], [3, 4], [5]]
思路
首先 遍历 Arr 的每个元素 是基本 Arr extends [infer First, ...infer Rest]
控制 chunk
是否满足 传入的 长度, 只需要 判断 chunk["length"] extends ItemLen
然后就是 判断 Arr 取出的 元素 是往 chunk
里面放, 还是 新起一个 chunk
TupleToNestedObject
实现 [a, b, c], 1
=> { a: { b: { c: 1 } } }
思路
遍历 Keys 每个元素
开始构造 对象, 对象的key
必须满足 keyof any
, () => void
是不能做键的,
然后判断 Rest
还是不是 数组
, 是的继续调用 TupleToNestedObject
, 否则 直接赋值 Value
PartialObjectPropByKeys
实现 对象指定 key
可选
思路
指定的 key
可选的意思 是不是 可选 key
单独拎出来 构建一个, 剩下的 再构建一个, 这两类型 交叉
是不是就是我们要的呢.
K in keyof T as K extends Keys ? never : K
排除可选 key
[K in Keys as K extends keyof T ? K : never]
这里记得要还要满足 keyof T
其实我们 还可以 用 ts 内置的高级类型
Extract<keys1, keys2>
从 key1
中 去除 与key2
相交的那部分
Pick<T, keys>
从 T
中 构建出 key
为 keyof keys
的新类型
Partial<T>
将 T
的所有键 变成 可选
Omit<T, keys>
构建一个 从 T 中 keyof keys
新类型
// ts 只有在用到的时候才会去计算
type PartialObjectPropByKeys1<
T extends Record<any, any>,
Keys extends keyof any,
> = Partial<Pick<T, Extract<keyof T, Keys>>> & Omit<T, Keys>;
UnionToTuple
函数的重载
第一种
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: any, b: any) {
return a + b;
}
第二种
interface Func {
(name: string): string;
(name: number): number;
}
declare const fn: Func;
fn('1');
第三种
type Func1 = ((name: string) => string) & ((name: number) => number);
declare const fn1: Func1;
fn1'1');
思路
联合类型 转 元组类型
我们需要 把 联合类型的 每一项 取出来
放进 元组里
那怎么取出来呢? 或者说 怎么去把 联合类型的每一项 都能单独
成一个新类型, 然后我们只需要 取这个新类型 就好
我们容易遍历的 数组 / 字符串 / 对象
, 数组 字符串 不现实, 所以 对象
咦, 我们之前是不是 实现过联合转交叉
, 但是我们之前实现的 交叉
针对的是类型的交叉, 比如我们传 "1" | 1 => never
交叉 函数的重载 => 通过交叉来重载
, 我们把 联合转交叉的结果 再变成 () => xx & () => yy
的交叉
然后再 分别取 ReturnType
join
declare function join<Delimiter extends string>(
delimiter: Delimiter,
): <Items extends string[]>(...parts: Items) => JoinType<Items, Delimiter>;
type RemoveFirstDelimiter<Str extends string> =
Str extends `${infer _}${infer Rest}` ? Rest : Str;
type JoinType<
Items extends any[],
Delimiter extends string,
Result extends string = '',
> = Items extends [infer Cur, ...infer Rest]
? JoinType<Rest, Delimiter, `${Result}${Delimiter}${Cur & string}`>
: RemoveFirstDelimiter<Result>;
let res = join('-')('guang', 'and', 'dong');
DeepCamelize
实现 索引的 Camelize
思路
主要的地方就是 key extends ${infer First}_${infer Rest}
AllKeyPath
实现 拿到一个索引类型的所有 key 的路径
思路
主要逻辑 是 如果 Obj[key] 是对象 继续获取, 否则 拼接 path
{}[keyof Obj] 这个就类似 [][number] 取值
type Obj = {
a: '1';
b: 2;
};
type o = Obj[keyof Obj];
type Arr = [1, 2, 3, 4, '5'];
type a = Arr[number];
Defaultize
实现一个高级类型,对 A、B 两个索引类型做合并,如果是只有 A 中有的不变,如果是 A、B 都有的就变为可选,只有 B 中有的也变为可选
思路
三部分 交叉 就好
Pick<A, Exclude<keyof A, keyof B>>
=> A 中排除 B 有的
Partial<Pick<A, Extract<keyof A, keyof B>>>
A, B 都有的
Partial<Pick<B, Exclude<keyof B, keyof A>>>
B 中排除 A 有的