当前位置: 首页 > 知识库问答 >
问题:

typescript - TypeScript 中未声明属性错误提示不一致?

鞠凌龙
2024-04-12

如下代码:

interface IPerson {  name: string;  others: { hobby: string };}function testFn(type: IPerson) {  console.log("�� ~ testFn ~ type:", type);}testFn({ name: "123", age: 18, others: { hobby: "跑步", name1: "124" } });const p1 = { name: "123", age: 18, others: { hobby: "跑步", name1: "124" } };testFn(p1);

在 vs code 中,有一个报错提示:
image.png

我有2个疑问:

  1. 为什么 age、name1 都没有在 IPerson 中声明,但只提示了 name1 没有声明的错误,没有 age 的错误提示?
  2. 把字面量形式的对象赋值给 p1 变量,然后传给 testFn,为啥此时没有任何错误提示了呢?

尝试将这段代码放在多个地方,排除了 tsconfig.json 配置的原因。

共有2个答案

糜博远
2024-04-12

区别在于前者你是直接传了一个字面量进去,后者是通过一个中间变量(且未声明类型)传入的。

对于前者而言 TS 的类型检查会更严格,这一特性叫 Freshness(默认开启,可通过 tsconfig.json 里的 suppressExcessPropertyErrors 配置项关闭)。而后者就是普通的鸭子类型检查。

至于为啥有这种特性,感兴趣可以自己搜索了解。

P.S. 问题一并不是个问题,只是 TS 报错是一种“懒检查”,即同类型的错误已经检查到了后面就跳过了,这样能显著地加快检查速度。你把 name1 删了就能看到 age 也一样报错了。

双浩涆
2024-04-12

在 TypeScript 中,当你尝试将一个对象传递给一个函数或赋值给一个变量时,如果对象的属性不完全符合接口或类型的定义,你会收到一个错误。但是,TypeScript 对额外的属性(不在接口或类型定义中的属性)和缺失的属性有不同的处理方式。

  1. 为什么只提示了 name1 没有声明的错误,没有 age 的错误提示?
* **额外的属性**:当你尝试将一个对象传递给一个函数或赋值给一个变量时,如果该对象有额外的属性(即不在接口或类型定义中的属性),TypeScript 通常会忽略这些额外的属性,并不会报错。这是 TypeScript 的一种设计选择,旨在允许一定程度的灵活性。在你的例子中,`age` 是一个额外的属性,因此 TypeScript 没有报错。* **缺失的属性**:相反,如果对象缺少接口或类型定义中的属性,TypeScript 会报错。在你的例子中,`IPerson` 接口定义了 `name` 和 `others` 属性,但没有定义 `name1` 属性,所以当你尝试传递一个包含 `name1` 属性的对象时,TypeScript 会报错。
  1. 为什么把字面量形式的对象赋值给 p1 变量,然后传给 testFn 时没有任何错误提示了呢?
* 当你将字面量形式的对象赋值给 `p1` 变量时,TypeScript 会尝试推断 `p1` 的类型。由于字面量对象具有 `name`、`age` 和 `others` 属性,TypeScript 会推断 `p1` 的类型为 `{ name: string; age: number; others: { hobby: string; name1: string } }`。* 当你将 `p1` 传递给 `testFn` 函数时,TypeScript 会比较 `p1` 的类型(即 `{ name: string; age: number; others: { hobby: string; name1: string } }`)和 `testFn` 函数的参数类型(即 `IPerson`)。由于 `IPerson` 只定义了 `name` 和 `others` 属性,而 `p1` 的类型包含了这两个属性以及额外的 `age` 属性,因此 TypeScript 不会报错。如前所述,TypeScript 允许额外的属性。

总的来说,TypeScript 对额外的属性和缺失的属性有不同的处理方式,这导致了你所观察到的错误提示不一致的现象。

 类似资料:
  • 主要内容:CalcThirdPartyJsLib.js 文件代码:,Calc.d.ts 文件代码:,CalcTest.ts 文件代码:,CalcTest.js 文件代码:,实例TypeScript 作为 JavaScript 的超集,在开发过程中不可避免要引用其他第三方的 JavaScript 的库。虽然通过直接引用可以调用库的类和方法,但是却无法使用TypeScript 诸如类型检查等特性功能。为了解决这个问题,需要将这些库里的函数和方法体去掉后只保留导出类型声明,而产生了一个描述 JavaS

  • 主要内容:类型断言(Type Assertion),类型推断,变量作用域变量是一种使用方便的占位符,用于引用计算机内存地址。 我们可以把变量看做存储数据的容器。 TypeScript 变量的命名规则: 变量名称可以包含数字和字母。 除了下划线 _ 和美元 $ 符号外,不能包含其他特殊字符,包括空格。 变量名不能以数字开头。 变量使用前必须先声明,我们可以使用 var 来声明变量。 我们可以使用以下四种方式来声明变量: 声明变量的类型及初始值: 例如: 声明变量的类型,

  • TypeScript 编译器会将程序中多个具有相同名称的声明合并为一个声明。 但这并不是说 TypeScript 会随意的合并两个名称相同的字符串变量,这显然是不符合语法规定的,那么本节将介绍什么样的声明可以进行合并。 1. 慕课解释 TypeScript 中的声明会创建以下三种实体之一:命名空间、类型或值。 来看以下声明都创建了什么实体: 声明类型 创建了命名空间 创建了类型 创建了值 Name

  • 本节介绍 var let const 这三种变量的声明方式,重点讨论作用域与变量提升的相关知识点,这部分往往也是面试常考部分,需要多加注意。 说明: 在使用 TypeScript 进行变量声明时,一般建议添加对应的变量类型,由于本节是整个系列教程的第一节,还未介绍 TypeScript 的类型系统,所以本节的例子仍采用 JavaScript 的变量声明方式。虽然在变量声明时没有添加变量类型,但是

  • 概述 在下面的代码中,我已经完全理解了。这就是为什么我们使用鸭式打字。 问题 当我将赋给字符串值时,为什么没有因为索引签名而出现错误? 请用你的答案简单解释一下。如果我的索引签名的概念还不清楚。

  • My Express服务器具有以下代码: 头盔()和express都有错误。json()调用: helmet():没有重载匹配此调用。上次重载出现以下错误。类型参数(req:IncomingMessage,res:ServerResage,下一个:(err?:未知)= 表示json():没有与此调用匹配的重载。上一次重载导致以下错误。“NextHandleFunction”类型的参数不能分配给“P