加入收藏 | 设为首页 | 会员中心 | 我要投稿 晋中站长网 (https://www.0354zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 移动互联 > 评测 > 正文

TypeScript 中高级应用与完美实践

发布时间:2019-08-02 11:09:27 所属栏目:评测 来源:AlloyTeam
导读:当我们讨论 TypeScript 时,我们在讨论什么? TypeScript 的定位 JavaScript 的超集 编译期行为 不引入额外开销 不改变运行时行为 始终与 ESMAScript 语言标准一致 (stage 3 语法) TypeScript 中的 Decorator 较为特殊,为 Angular 团队和 TypeScript 团队

删除 map 的一部分

  1. type Omit<T, K> = Pick<T, Exclude<keyof T, K>>; 
  2. /* 
  3.     default: number 
  4.  */ 
  5. type DefaultSizeMap = Omit<BiggerSizeMap, 'big'>; 

保留 set 的一部分

  1. type Extract<T, U> = T extends U ? T : never; 
  2.   
  3. type Result = 1 | 2 | 3 | 'error' | 'success'; 
  4. type StringResult = Extract<Result, string>;    // 'error' | 'success 

删除 set 的一部分

  1. type Exclude<T, U> = T extends U ? never : T; 
  2. type NumericResult = Exclude<Result, string>;    // 1 | 2 | 3 

获取函数返回值的类型。但要注意不要滥用这个工具类型,应该尽量多手动标注函数返回值类型。理由开篇时提过, 契约高于实现 。用 ReturnType 是由实现反推契约,而实现往往容易变且容易出错,契约则相对稳定。另一方面,ReturnType 过多也会降低代码可读性。

  1. type ReturnType<T> = T extends (...args: any[]) => infer R ?  R : any; 
  2.   
  3. function f() { return { a: 3, b: 2}; } 
  4. /* 
  5.     a: number 
  6.     b: number 
  7.  */ 
  8. type FReturn = ReturnType<f>; 

以上这些工具类型都已经包含在了 TS 标准库中,在应用中直接输入名字进行使用即可。另外,在这些工具类型的实现中,出现了 infer、never、typeof 等关键字,在后文我会详细解释它们的作用。

类型的递归

TS 原生的 Readonly 只会限制一层写入操作,我们可以利用递归来实现深层次的 Readonly。但要注意,TS 对最大递归层数做了限制,最多递归 5 层。

  1. type DeepReadony<T> = { 
  2.     readonly [P in keyof T]: DeepReadony<T[P]> 
  3.   
  4. interface SomeObject { 
  5.   a: { 
  6.     b: { 
  7.       c: number; 
  8.     }; 
  9.   }; 
  10.   
  11. const obj: Readonly<SomeObject> = { a: { b: { c: 2 } } }; 
  12. obj.a.b.c = 3;    // TS不会报错 
  13.   
  14. const obj2: DeepReadony<SomeObject> = { a: { b: { c: 2 } } }; 
  15. obj2.a.b.c = 3;    // Cannot assign to 'c' because it is a read-only property. 

never infer typeof 关键字

never 是 | 运算的幺元,即 x | never = x 。例如之前的 Exclude<Result, string> 运算过程如下:

TypeScript 中高级应用与完美实践

infer 的作用是让 TypeScript 自己推断,并将推断的结果存储到一个临时名字中,并且只能用于 extends 语句中。它与泛型的区别在于,泛型是声明一个 “参数”,而 infer 是声明一个 “中间变量”。infer 我用得比较少,这里借用一下官方的示例。

  1. type Unpacked<T> = 
  2.     T extends (infer U)[] ? U : 
  3.     T extends (...args: any[]) => infer U ? U : 
  4.     T extends Promise<infer U> ? U : 
  5.     T; 
  6.   
  7. type T0 = Unpacked<string>;  // string 
  8. type T1 = Unpacked<string[]>;  // string 
  9. type T2 = Unpacked<() => string>;  // string 
  10. type T3 = Unpacked<Promise<string>>;  // string 
  11. type T4 = Unpacked<Promise<string>[]>;  // Promise<string> 
  12. type T5 = Unpacked<Unpacked<Promise<string>[]>>;  // string 

(编辑:晋中站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读