参考:
15 个提高开发效率的 TypeScript 小技巧
天花板级别类型体操
⚪ ? 与 !
?
为可选链式编程,js、ts 皆可使用,遇到 null 或 undefined 就不会再向下执行!
叫非空断言操作符,为 Ts 专属语法,断言某变量一定不为 null 或 undefined- 不使用
!
- 使用
!
⚪ 断言覆盖
**as unknown as otherType**
** 可覆盖重写原类型。 比 any 优雅太多**
| let number = 12; let str: string; str = number as unknown as string;
|
⚪ keyof 与 typeof
- typeof 可以用于类型判断,function 定义的函数会返回函数类型,const 常量定义的变量也可转为其对应的类型
- keyof 则可返回 类型上已知的公共属性名
二者可以结合使用
| const obj = { name: "目力先辈", age: 24, };
|
如果想把 obj 转为'name' | 'age'
这种类型,以在某些业务场景中达到更好的代提示和类型限制,可以这样:
先用 typeof
把 obj 转为 类型,然后将通过 keyof
获取类型上已知的属性名
| type objType = keyof typeof obj;
|
⚪ 将对象键值的类型转为联合类型
| interface Obj { name: string; sex: number; age: number; body: { hand: string; }; } type ObjType = Obj[keyof Obj];
|
⚪ const 和 let 类型推导的区别
const 声明的常量的类型为**<font style="color:rgb(51, 51, 51);">字面量类型</font>**
| const a = 1; const d = "2";
const [b, c] = [1, "2"];
const d = { e: 1, f: "2", };
|
let 声明的变量时,类型会被推导
**as const**
** 断言:**将推导的类型强转为字面量。可理解为 let 转 const
| const arg = { b: 1 }; const fn = (params: { b: 1 }) => {};
fn(arg);
const arg = { b: 1 } as const;
|
通过 const 将对象的值作为联合类型
⚪ 函数返回字面量而非 String
| const ReturnConstStringFn = <Str extends string[]>(val: [...Str]) => val;
|
⚪ 获取 interface 中的类型
| interface IType { name: string; body: Array<{ hand: string; }>; }
type Str = IType["body"][number]["hand"];
|
⚪ 模式匹配
| type arr = [1, 2, 3];
type num = "123";
type FirstArr<Arr> = Arr extends [infer First, ...infer Rest] ? First : Arr;
type FirstNum<Num> = Num extends `${infer First}2${infer Rest}` ? `${First}_${Rest}` : Num;
const arrParm: FirstArr<arr> = 1;
const numParm: FirstNum<num> = "1_3";
|
⚪ 互斥类型
| type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
type XOR<T, U> = (Without<T, U> & U) | (Without<U, T> & T);
|
⚪ 函数类型中的参数关系限定
例如:如果 a 为 1 的时候,b 必须 传 ‘1’,a 为 2,b 必须传 2
- 可以利用函数重载
(函数可以重复声明,但是只能有一个函数拥有函数体去具体实现)
| function fn(a: 1, b: "1"): void; function fn(a: 2, b: "2"): void; function fn(a: 1 | 2, b: "1" | "2"): void { }
|
- 可以利用泛型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| interface BType { 1: "1"; 2: "2"; }
function fn<AType extends keyof BType>(a: Atype, b: BType[AType]): void { }
function fn<AType extends keyof BType>( a: Atype, b: AType extends "1" ? BType["1"] : BType["2"] ): void { }
|
- 如果函数只有一个参数。可以直接用联合类型声明参数可能的情况。
| function fn({ a, b }: { a: 1; b: "1" } | { a: 2; b: "2" }): void { }
|
⚪ 下划线 转 小驼峰。
** <T> extend any ? [type] : never**
可触发 ts 深层计算(即鼠标悬停类型上,可以看到计算后的结果)
| type Camel<Obj> = Obj extends any ? { [key in keyof Obj as CamelCase< Lowercase<key & string> >]: Obj[key] extends Array<infer Ele> ? Array<CamelCase<Ele & string>> : Obj[key] extends Record<string, any> ? Camel<Obj[key]> : Obj[key]; } : never;
type CamelCase<Str extends string> = Str extends `${infer Left}_${infer Rest}` ? `${Left}${CamelCase<Capitalize<Rest>>}` : Str;
|
原数据:
| type source = { Name: string; Naj_age: number; sex: { One_man: number; Two_woman: string; Other: symbol; }; hobby: Array<"paly_good_game" | "one_day_sleep">; };
|
类型转换后: