Typescript 练习记录

148 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

第一题

以下代码为什么会提示错误,应该如何解决?

type User = {
  id: number;
  kind: string;
};

function makeCustomer<T extends User>(u: T): T {
  // Error(TS 编译器版本:v4.4.2)
  // Type '{ id: number; kind: string; }' is not assignable to type 'T'.
  // '{ id: number; kind: string; }' is assignable to the constraint of type 'T', 
  // but 'T' could be instantiated with a different subtype of constraint 'User'.
  return {
    id: u.id,
    kind: 'customer'
  }
}

报错原因

  • 泛型 T由于是在调用该函数的时候才能确定,T类型有可能会存在别的类型,因此返回值{id: u.id, kind: 'customer'}, 不一定符合泛型T
  • 例如 上述列子: MyUser的类型符合User类型的约束,但是还存在age类型,显然函数的返回值,并不满足MyUser类型。

解决办法

  • 让返回值满足泛型T
function makeCustomer<T extends User>(u: T): T {
  return {
    ...u,
    id: u.id,
    kind: 'customer'
  };
}
  • 在不确定泛型T的情况下不推荐类型断言。

第二题

本道题我们希望参数 a 和 b 的类型都是一致的,即 a 和 b 同时为 number 或 string 类型。当它们的类型不一致的值,TS 类型检查器能自动提示对应的错误信息。

function f(a: string | number, b: string | number) {
  if (typeof a === 'string') {
    return a + ':' + b; // no error but b can be number!
  } else {
    return a + b; // error as b can be number | string
  }
}

f(2, 3); // Ok
f(1, 'a'); // Error
f('a', 2); // Error
f('a', 'b') // Ok

答案

  • 函数重载
function f(a:string, b:string):string
function f(a:number, b:number):number
function f(a: string | number, b: string | number) {
  if (typeof a === 'string') {
    return a + ':' + b; // no error but b can be number!
  } else {
    return a + b; // error as b can be number | string
  }
}
  • 泛型约束
function f<T extends string|number>(a:T, b:T) {
  if (typeof a === 'string') {
    return a + ':' + b; // no error but b can be number!
  } else {
    return a + b; // error as b can be number | string
  }
}

习题出自 github.com/semlinker/a…