Loading

typescript 中严格字面量类型检查的理解

个人关于 TS 中 Strict object literal assignment checking 的理解

Strict object literal assignment checking

Strict object literal assignment checking by ahejlsberg · Pull Request #3823 · microsoft/TypeScript

案例

interface IStudent{
  name: string
  id: string
}

const stu1: IStudent = {
  name: "https://www.cnblogs.com/jasongrass/",
  id: "123",
  score: 90 // error 
}

const obj = {
  name: "https://www.cnblogs.com/jasongrass/",
  id: "123",
  score: 90
}

const stu3: IStudent  = obj  // ok

在上面 stu1 赋值时,会出现如下错误:

语法上的原因,是因为有上面提到的 Strict object literal assignment checking,但怎么理解呢?

理解

const stu1: IStudent = {
  name: "https://www.cnblogs.com/jasongrass/",
  id: "123",
  score: 90 // error 
}

来看 stu1 的定义,stu1 是一个标识符,一个指向对象的引用,而且这个对象的初始化引用类型,被定义成了 IStudent(其中没有 score 这个属性的定义)
这意味着,在后续使用中,无法通过 stu1 访问到 score 这个属性,这通常意味着代码错误或者设计不合理。

当然,语法上,可以先将 stu1 转换成 any 类型,然后再访问,如

const stu11 = stu1 as any
const score  = stu11.score

但这失去了类型约束的意义,而且令人难以理解。

而先定义了 obj,然后再通过 const stu3: IStudent = obj 赋值给 stu3 就没有问题。
这里,虽然 stu3 中无法直接访问 score 这个属性了,但是 obj 这个引用保留了完整的数据,可以用于访问 score 属性。

另外,这里还涉及到的一个思想,是 TS 中关于类型的设计。TS 中的类型,不需要如 java/C# 中严格匹配,只需要 “形似” 就可以,也就是所谓的鸭子类型。
https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-oop.html#types-as-sets 所述,将 TS 的类型理解成集合的概念,会好理解很多,尤其对于使用 java/C# 等强类型面向对象语言的同学。

案例2

const stu4 = {
  name: "j",
  id: "456",
  score: 90
}

print({ name: "j", id: "456", score: 90 }) // error
print(stu4)

function print(student: IStudent) {

}

这里其实是一样的,实参 { name: "j", id: "456", score: 90 } 中的 score 属性,在赋值给形参 student 之后,将“消失”,
将 score 定义在这里没有意义,是多余的,通常意味着代码书写错误。

posted @ 2023-07-15 17:24  J.晒太阳的猫  阅读(23)  评论(0编辑  收藏  举报