个人关于 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 stu2 = {
name: "https://www.cnblogs.com/jasongrass/",
id: "123",
score: 90
}
const stu3 = stu2 // 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
但这失去了类型约束的意义,而且令人难以理解。
而先定义了 stu2,然后再通过 const stu3 = stu2
赋值给 stu3 就没有问题。
这里,虽然 stu3 中无法直接访问 score 这个属性了,但是 stu2 这个引用保留了完整的数据,可以用于访问 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 定义在这里没有意义,是多余的,通常意味着代码书写错误。