《Effective TypeScript 》-- 条款11: 额外属性检查的局限性

360 阅读3分钟

条款11: 额外属性检查的局限性

目录:

  • 理解什么是额外类型检查;
  • 理解为什么会存在额外类型检查、和常规的类型检查有什么区别;
  • 掌握局限性表现在什么地方;

1. 额外类型检查

额外类型检查是指当将值或者变量引用赋值给另一个对象变量时,会触发类型检查器的一种检查方式。

常规的类型检查主要是判断两个变量类型是否是具有子集的关系,如果是具有子集的关系,则可以进行复制,见条款7。

额外类型属性检查的一种表现形式为,字面量对象赋值时的属性检查,有时也被称为严格的字面量检查,首先我们看一下下面的例子:

interface IA {
  name: string;
  age: number;
}

const a: IA = {
  name: 'yunxi',
  age: 18,
  hobby: ['chouyan', 'hejiu', 'tangtou']
}

此时我们的代码会报错,

Object literal may only specify known properties, and 'hobby' does not exist in type 'IA' 对象文本只能指定已知属性,并且类型‘IA’中不存在‘hobby’。

他会告诉我们,我们想要将一个字面量对象赋值给类型IA时,会触发一个额外属性的检查,他会告诉我们我们想要赋值的对象中的属性是否满足要求。他仅仅是发生在字面量赋值的场景下,所以也称为“严格的字面量检查”;

当我们利用一个中间变量作为转换时,上述的问题就不复存在了:

interface IA {
  name: string;
  age: number;
}

const obj = {
  name: 'yunxi',
  age: 18,
  hobby: ['chouyan', 'hejiu', 'tangtou']
}

const a: IA = obj;

因为严格的字面量检查只发生在字面量赋值的时候,const obj = {},这个赋值语句发生了字面量检查,但是将 obj 赋值给 a 时,没有额外类型检查,因为 obj 是一个内存地址的引用,而对于静态类型检查器而言,在代码未运行时,他并不知道变量地址的一个真实的类型,所以他只能通过上下文的推导,所以对于 obj 这个对象,他经过推导的类型是

interface IB {
  name: string;
  age: number;
  hobby: string[]
}

而常规的类型检查的赋值,是根据类型的值的集合(条款7),判断两个类型是否是子集的方式判断是否可以进行复制,从上面看 IB 是 IA 集合的一个子集,所以将 IB 赋值给 IA 是有效的;

interface IA {
  name: string;
  age: number;
}

interface IB {
  name: string;
  age: number;
  hobby: string[];
}

const obj: IB = {
  name: 'yunxi',
  age: 18,
  hobby: ['chouyan', 'hejiu', 'tangtou']
}

const a: IA = obj;

上面的例子表现了额外的类型的检查和常规的类型检查的一个区别,额外的类型检查发生在字面量赋值的时候,他会针对将要赋值给变量的对象字面量进行严格的属性检查,而常规的赋值检查是判断类型是否是子集;

“一个相关”的检查

我们先来看一个例子

interface IC {
  name?: string;
  age?: number;
}

const c2 = {
  hobby: ['tangtou']
}

const c1: IC = c2;

Type '{ hobby: string[]; }' has no properties in common with type 'IC'. 类型‘{hobby:string[];}’与类型‘IC’没有相同的属性。

这个 IC 类型是一个任何属性都可选的一个类型,理论上来说,任何对象类型都是 IC 属性的一个子集,但是对于这种全是可选属性的弱类型,TS 检查器在校验时增加了“一个相关”的类型校验,字面上的意思就是,赋值时,必须存在有一个共同的属性,否则则会报错。而且不能通过中间变量进行转换。

总结

  1. 对于字面量赋值时,会触发额外属性检查,会严格校验对象的属性是否符合要求;但是存在局限性,可以通过中间变量绕过严格的字面量校验,转为常规的赋值校验(是否为子集);
  2. 对于一个可选属性的弱类型,TS 增加了一个至少有一个共同类型的判断;

手稿:

IMG_2456.HEIC.JPG.JPG