Skip to content

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

Published: at 17:24

个人关于 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 定义在这里没有意义,是多余的,通常意味着代码书写错误。


原文链接: https://blog.jgrass.cc/posts/typescript-strict-object-literal-assignment-checking/

本作品采用 「署名 4.0 国际」 许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。