-
基本类型,完全匹配才可以被赋值。
-
函数类型,参数可以少传不能多传,返回值要求返回则必须返回,不要求返回,返回了也不报错。
-
对象类型,有些特殊的要求。
下面介绍下对象类型的类型兼容性:
1,它是鸭子吗
“当看到一只鸟走起来像鸭子、游起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
所以有一个鸭子分辨法:
如果 B 能赋值给 A(A = B),则 B 的类型 typeB
兼容 A 的类型 typeA
。
也就是说,目标(鸭子)类型
typeA
需要一些特征,赋值类型typeB
只要能满足即可。
举例:
interface Duck {
sound: "嘎嘎";
canSwim: Boolean;
}
let user = {
name: "伪装成鸭子",
age: 12,
sound: "嘎嘎" as "嘎嘎",
canSwim: true,
};
let duck: Duck = user;
注意点1
sound: "嘎嘎" as "嘎嘎",
为什么要这样写?
因为在接口中 sound
字段就是用 "嘎嘎"
这个确定的字面量类型来约束的。所以在使用该接口时,sound
只能赋值为它。
但是在使用时,对 sound
的赋值会被推断为 string
类型,所以要用类型断言 as
来告诉 ts 它的类型。
所以,如果 canSwim
像下面这样定义,则使用时也得这样:canSwim: true as true
interface Duck {
sound: "嘎嘎";
canSwim: true;
}
注意点2
看起来变量 duck
现在有4个属性,但只能使用接口 Duck
约束的2个字段。
console.log(duck.sound);
// 报错 Property 'name' does not exist on type 'Duck'.ts(2339)
console.log(duck.name);
注意点3
直接使用对象字面量赋值,会触发 ts 更加严格的类型检查。
let duck: Duck = {
// Object literal may only specify known properties, and 'name' does not exist in type 'Duck'.ts(2353)
name: "伪装成鸭子",
age: 12,
sound: "嘎嘎" as "嘎嘎",
canSwim: true,
};
那为什么下面这样就可以呢?
let user = {
name: "伪装成鸭子",
age: 12,
sound: "嘎嘎" as "嘎嘎",
canSwim: true,
};
let duck: Duck = user;
首先,一般情况下不会这样多此一举,但 user 如果是一个函数执行的返回值,并且函数传参不同返回值就不同, ts 会考虑这样的情况。
换句话说,既然直接使用对象字面量赋值,那说明 每个字段都是确认的,所以得严格一点。
function getUser() {
return {
name: "伪装成鸭子",
age: 12,
sound: "嘎嘎" as "嘎嘎",
canSwim: true,
};
}
let duck: Duck = getUser();
也可以使用类型断言来规避这个错误
let duck: Duck = {
name: "伪装成鸭子",
age: 12,
sound: "嘎嘎" as "嘎嘎",
canSwim: true as true,
} as Duck;
// 或
let duck: Duck = <Duck>{
name: "伪装成鸭子",
age: 12,
sound: "嘎嘎" as "嘎嘎",
canSwim: true as true,
}
2,实际应用
注意点 2 是一个关键点。
举例:接口返回字段有很多,我们只需要其中的几个。如果使用接口中没有定义的字段,就会报错!
interface User {
nickname: string;
id: string;
}
const responseUser = {
nickname: "xx",
id: "fafd12312",
age: 18,
// ...
};
let user: User = responseUser;
console.log(user.nickname);
// Property 'age' does not exist on type 'User'.ts(2339)
console.log(user.age);
类的继承同理
class User {
name: string = ''
age: number = 18
}
class AdminUser extends User {
role: string = '123'
}
// 因为约束为 User,所以不能使用 role 属性。
const admin: User = new AdminUser()
扑克牌练习中,也用到了这个特性。
以上。