类型性质
类型推论
类型推论即类型是在何处被推断的
- 变量和成员在初始化值时,将根据值的类型设置对应的类型
- 若值为数组,则会推断数组元素类型为初始化值的元素类型的联合类型
- 在有上下文的情况下,参数类型可以被自动推断,指定参数类型将忽略上下文推断
示例
ts
// 根据初始值设置类型
let str = "777"; //let str: string
// str = 777 //Error
// 对数组元素设置联合类型
let arr = [false, null]; //let arr: (boolean | null)[]
arr = [null, null, true];
// arr = [1] //Error
// 根据上下文,这里指定了 `arr` 元素的类型为 `number` ,所以 `cur` 参数被推断为 `number` 类型
function getSum(arr: number[]) {
return arr.reduce((sum, cur) => (sum += cur), 0);
}类型断言
类型断言即告诉编辑器某变量或成员在当前上下文的具体类型
- 使用
<Type>variable的格式指定变量的类型 - 使用
variable as Type的格式指定变量的类型 - 在 JSX 中只允许使用
as进行断言 - 如果某变量或成员非
null,可以使用variable!的格式进行说明
类型保护
类型保护即告诉编译器某变量或成员在给定的上下文中的具体类型,使用类型保护可以避免重复的类型断言
- 使用
===运算符或||运算符对成员进行null类型保护,其用法同 js - 使用
typeof类型保护确保基本类型成员的类型,其用法同 js - 使用
instanceof类型保护确保实例类型成员的类型,其用法同 js - 使用自定义类型保护确保成员的具体类型
- 自定义类型保护需要声明一个函数,其返回值是布尔类型,但使用类型谓词进行描述
- 类型谓词描述的格式为
parameterName is Type,parameterName为函数中的某个参数
ts
class Rect {
width: number;
height: number;
area: number;
}
const isRect = (obj: any): obj is Rect =>
typeof obj === "object" &&
typeof obj.width === "number" &&
typeof obj.height === "number";
const unkonw = {};
if (isRect(unkonw)) {
console.log(unkonw.area);
}可辨识联合
可辨识联合又叫 标签联合 或 代数数据联合,即对于多个单例类型的联合,可以通过可辨识的属性实现该属性上的类型保护,需要具有以下三个要素:
- 具有普通的单例类型属性 (可辨识的特征)
- 一个类型别名包含了那些类型的联合 (联合)
- 此属性上的类型保护
示例
ts
interface A {
name: "a";
a: string;
}
interface B {
name: "b";
b: number;
}
type AB = A | B;
function test(arg: AB) {
switch (arg.name) {
case "a":
return "a";
case "b":
return "b";
default:
return "";
}
}类型兼容性
结构类型与名义类型
- 结构类型: 只使用其成员来描述类型的方式
- 名义类型: 通过明确的声明或类型的名称决定类型的方式
类型兼容性
- ts 中的类型兼容性基于结构子类型
- 使用该方式只检测类型的组成结构而非名称
兼容性规则
- 基本规则:若 X 兼容 Y ,则 Y 至少具有与 X 相同的属性
- 比较函数
- 比较的是参数列表
- 比较枚举类型
- 数字枚举类型与数字类型相互兼容
- 不同枚举类型之间互不兼容
- 比较类类型
- 只比较实例成员,不比较静态恒源和构造函数
- 若目标类型含有私有成员,则源类型必须含有来自同一个类的该私有成员
- 比较泛型接口
- 未指定泛型类型的泛型参数时,会将泛型参数当做
any处理后进行比较 - 指定泛型类型的泛型参数时,沪江泛型参数转换为具体的类型后进行比较
- 未指定泛型类型的泛型参数时,会将泛型参数当做