登录/注册
小开开
2649
占位
2
占位
0
浏览量
占位
粉丝
占位
关注
TypeScript-泛型约束
小开开
2020-12-04 17:17:16 2020-12-04
86
0

泛型约束

必须谨慎使用类型变量,参考下面的例子:

// 定义泛型函数
function getLength<T>(arg: T): number {
// 错误,编译器不知道类型变量T是否包含属性length,默认为不存在
// error TS2339: Property 'length' does not exist on type 'T'
return arg.length;
}

上例中没有任何地方表明 T 类型的参数 arg 包含属性 length,因而编译器认为不存在属性 length 报错。为了改正上述代码,需要约束类型变量 T 必须包含属性 length

语法

类型变量 extends 类型

类型约束关键字为 extends,和继承关键字一样。实际上,类型约束跟继承同义,类型变量继承了被约束类型的所有成员

// 声明接口
interface WithLength {
length: number;
}
// 正确,T现在被接口类型WithLength约束,包含属性 length
function getLength<T extends WithLength>(arg: T): number {
return arg.length;
}

默认类型

参考下面的例子:

interface MyType<T> {
value: T;
}
// error TS2314: Generic type 'MyType<T>' requires 1 type argument(s)
let a: MyType = {
value: "hello world"
}

泛型在使用的时候必须用实际类型取代类型参数,假如同上面那样,编译器就无法判定a.value的实际类型是什么(有可能是任何类型),因而报错。修正这个错误很简单,只需要在使用的时候传递类型参数即可:

// 正确
let a: MyType<string> = {
value: "hello world"
}

每次都用尖括号语法注解确实挺烦的,尤其是在有些情况下,其他人使用 MyType 接口的时候可能并不知道这是一个泛型接口声明。TypeScript提供了默认类型语法:

类型变量 = 类型

参考下面的例子:

interface MyType<T = string> {
value: T;
}
// 正确,在类型参数没有显示指定的情况下,采用了默认类型 string
let x1: MyType = {
value: "hello world"
}
// 等价于
let x1: MyType<string> = {
value: "hello world"
}
// 错误, error TS2322: Type 'number' is not assignable to type 'string'
let x2: MyType = {
value: 123
}
暂无评论