1对extends的理解

  1. type User = {
  2. id: number;
  3. kind: string;
  4. };
  5. function makeCustomer<T extends User>(u: T): T {
  6. return {
  7. id: u.id,
  8. kind: 'customer'
  9. }
  10. }
  11. // Error(TS 编译器版本:v4.4.2)
  12. // Type '{ id: number; kind: string; }' is not assignable to type 'T'.
  13. // '{ id: number; kind: string; }' is assignable to the constraint of type 'T',
  14. // but 'T' could be instantiated with a different subtype of constraint 'User'.
  1. type User = {
  2. id: number;
  3. kind: string;
  4. };
  5. function makeCustomer<T extends User>(u: T): T {
  6. return {
  7. ... u,
  8. id: u.id,
  9. kind: 'customer'
  10. }
  11. 或者
  12. return Object.assign(u, {
  13. id: u.id,
  14. kind: 'customer'
  15. })
  16. }
  17. T extends User T的属性可能比User更多,直接返回User格式的类型是不行的,这样会导致丢失其他属性

2函数重载

  1. function f(a: string | number, b: string | number) {
  2. if (typeof a === 'string') {
  3. return a + ':' + b; // no error but b can be number!
  4. } else {
  5. return a + b; // error as b can be number | string
  6. }
  7. }
  8. f(2, 3); // Ok
  9. f(1, 'a'); // Error
  10. f('a', 2); // Error
  11. f('a', 'b') // Ok
  1. function f(a: string, b: string): string
  2. function f(a: number, b: number): number
  3. function f(a: CustomType, b: CustomType): CustomType {
  4. if (typeof a === 'string' || typeof b === 'string') {
  5. return `${a}:${b}`
  6. }
  7. return a + b
  8. }
  9. 先是定义两种情况,然后在实现里通过typeof判断值的类型,对不同情况来做不同处理

3把指定类型变成可选

  1. type Foo = {
  2. a: number;
  3. b?: string;
  4. c: boolean;
  5. }
  6. // 测试用例
  7. type SomeOptional = SetOptional<Foo, 'a' | 'b'>;
  8. // type SomeOptional = {
  9. // a?: number; // 该属性已变成可选的
  10. // b?: string; // 保持不变
  11. // c: boolean;
  12. // }
  1. type Foo = {
  2. a: string,
  3. b: number,
  4. c: boolean
  5. }
  6. // Simplify 数组扁平处理(确保类型属性是来自T类型的属性)
  7. type Simplify<T> = {
  8. [P in keyof T]: T[P]
  9. }
  10. 0. 这里的T就是上面定义的Foo类型,KFoo类型的属性
  11. 1. Pick<T,K> T中挑选出K属性
  12. 2. Partial<T> T中的所有属性变为可选
  13. 3. keyof T 获取T类型的所有属性
  14. 4. Exclude<T,K> T类型中删除掉K中所有属性
  15. 5. Pick<T,K> T类型中挑出剩下的类型
  16. 6. & 前面一部分跳出了要设置的属性,并把它们都设置成了可选,然后通过&加上没有选择的属性,保持这些属性原来的类型
  17. 7. Simplify<T> 代码提示会更友好,直接显示Foo的改变
  18. type SetOptional<T, K extends keyof T> =
  19. Simplify<Partial<Pick<T, K>> & Pick<T,Exclude<keyof T, K>>>

3.2把指定类型变成必需

  1. type Foo = {
  2. a: string,
  3. b: number,
  4. c: boolean
  5. }
  6. type Simplify<T> = {
  7. [P in keyof T]: T[P]
  8. }
  9. type SetRequired<T, K extends keyof T> =
  10. Simplify<Required<Pick<T,K>> & Pick<T, Exclude<keyof T, K>>>