TypeScript 的类型体操笔记,温故知新。
为接口新增字段 Append to object、返回正数字符串 Absolute、字符串转字母 String to Union
类型合并 Merge、字母大小写转换和连接字符串 KebabCase、两个接口类型的差值属性 Diff
中等挑战
一、为接口新增字段 Append to object
实现一个为接口添加一个新字段的类型。该类型接收三个参数,返回带有新字段的接口类型。
type AppendToObject<T extends Object, U extends keyof any, V> = {
    [K in keyof T | U]: K extends keyof T ? T[K] : V;
};
二、返回正数字符串 Absolute
实现一个接收 string,number 或 bigInt 类型参数的 Absolute 类型,返回一个正数字符串。
type Absolute<T extends number | string | bigint> = `${T}` extends `-${infer R}` ? `${R}` : `${T}`;
TypeScript 中,通过模板字符串将(number / bigint )数组转换为字符串时,编译器会自动进行转换
三、字符串转字母 String to Union
实现一个将接收到的String参数转换为一个字母Union的类型。
type StringToUnion<T extends string> = T extends `${infer L}${infer R}` ? L | StringToUnion<R> : never;
type StringToUnion<T extends string, U extends unknown[] = []> = T extends `${infer L}${infer R}` ? StringToUnion<R, [...U, L]> : U[number];
四、类型合并 Merge
将两个类型合并成一个类型,第二个类型的键会覆盖第一个类型的键。
type Merge<F, S> = {
    [K in keyof F | keyof S]: K extends keyof S ? S[K] : K extends keyof F ? F[K] : never;
};
五、字母大小写转换和连接字符串 KebabCase
Replace the camelCase or PascalCase string with kebab-case.
字符串替换 FooBarBaz -> foo-bar-baz
type KebabCase<S extends string> = S extends `${infer F}${infer R}` ? (R extends Uncapitalize<R> ? `${Uncapitalize<F>}${KebabCase<R>}` : `${Uncapitalize<F>}-${KebabCase<R>}`) : S;
TypeScript提供的工具类型:
Uppercase<StringType> 将字符串中的每个字符转换为大写版本。
Lowercase<StringType> 将字符串中的每个字符转换为等效的小写字母。
Capitalize<StringType> 将字符串中的第一个字符转换为等效的大写字母。
Uncapitalize<StringType> 将字符串中的第一个字符转换为等效的小写字母。
六、两个接口类型的差值属性 Diff
获取两个接口类型中的差值属性。
type Diff<O, O1> = {
    [K in keyof (O & O1) as K extends keyof (O | O1) ? never : K]: (O & O1)[K];
};
type Diff<O, O1> = Omit<O & O1, keyof (O | O1)>;
TypeScript提供的工具类型:
Omit<Type, Keys> 通过从 Type 中选择所有属性然后删除 Keys(字符串字面或字符串字面的并集)来构造一个类型。
//  | 和 & 的使用
type type1 = 1 | 2 | "3";
type type2 = 2 | "3" | 0;
type res1 = type1 | type2; // 0 | 1 | 2 | "3"
type res2 = type1 & type2; // 2 | '3'
//  | 和 & 在对象中的使用
type Foo = {
    name: string;
    age: string;
};
type Bar = {
    name: string;
    age: string;
    gender: number;
};
type result = keyof (Foo | Bar); // "name" | "age"
interface Colorful {
    color: string;
}
interface Circle {
    radius: number;
}
type ColorfulCircle = keyof (Colorful & Circle); // "color" | "radius"