首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >仅当缺少非可选接口属性和存在额外属性时,TypeScript as cast才会失败

仅当缺少非可选接口属性和存在额外属性时,TypeScript as cast才会失败
EN

Stack Overflow用户
提问于 2018-02-22 19:06:31
回答 2查看 1.3K关注 0票数 1

我在example.ts上本地运行tsc,我预计onePropMissing会出现警告或错误,因为c不是接口上的可选属性,然而,在onePropMissing中缺少c属性,并且我没有得到任何错误。

在那之后,我添加了一个示例,oneExtraProp,我也预料到它会失败,因为还有一个属性。

在这两个例子之后,我很确定extraAndOneMissing也会很好,不过,令我惊讶的是,台积电在这里抱怨道。

代码语言:javascript
运行
复制
interface InterfaceEverythingRequired {
  a: string;
  b: string;
  c: number;
}
// Expected to be OK, it's OK
const allPropsPresent = { a: 'a', b: 'b', c: 1 } as InterfaceEverythingRequired;
// Expected warning as c is missing, but TSC says it's OK
const onePropMissing = { a: 'a', b: 'b' } as InterfaceEverythingRequired;
// Expected warning as extraProp is present, but TSC says it's OK
const oneExtraProp = { a: 'a', b: 'b', c: 3, extraProp: 'no-issues' } as InterfaceEverythingRequired;
// After the last two examples, I expected to have no warnings, as
// there were no warnings for the extra property, nor the missing property
// but TSC complained
const extraAndOneMissing = { a: 'a', b: 'b', extraProp: 'what?' } as InterfaceEverythingRequired;

这里发生了什么?为什么错误的行为如此有趣?

我得到的错误是:

代码语言:javascript
运行
复制
Type '{ a: string; b: string; extraProp: string; }' cannot be 
converted to type 'InterfaceEverythingRequired'.
  Property 'c' is missing in type '{ a: string; b: string; 
extraProp: string; }'.
EN

回答 2

Stack Overflow用户

发布于 2018-02-22 19:40:15

您不应该使用as来输入变量。直接键入它们

代码语言:javascript
运行
复制
const onePropMissing: InterfaceEverythingRequired = { a: 'a', b: 'b' }; // error

TypeScript中的类型转换实际上只是类型断言,TypeScript的结构化类型系统在来自名义类型语言时导致了许多意想不到的结果。

许多典型的陷阱都在TypeScript FAQ中得到了解决。

票数 1
EN

Stack Overflow用户

发布于 2018-02-22 20:31:35

如果你像下面这样写你的例子,你会得到更好的错误信息:

代码语言:javascript
运行
复制
const allPropsPresent: InterfaceEverythingRequired = { a: 'a', b: 'b', c: 1 };
// Ok
const onePropMissing: InterfaceEverythingRequired = { a: 'a', b: 'b' }
// Property 'c' is missing
const oneExtraProp: InterfaceEverythingRequired = { a: 'a', b: 'b', c: 3, extraProp: 'no-issues' }
// Object literals may only specify known properties
const extraAndOneMissing: InterfaceEverythingRequired = { a: 'a', b: 'b', extraProp: 'what?' };
// Object literals may only specify known properties

现在,对于您的问题,为什么类型断言适用于除最后一种情况之外的所有情况,您需要考虑TypeScript中的结构类型:

{ a: 'a', b: 'b', c: 1 }{ a: 'a', b: 'b' }的一个子类型,因为它具有超类型的所有属性。

代码语言:javascript
运行
复制
let x: { a: 'a', b: 'b', c: 1 };
let y: { a: 'a', b: 'b' };
x = y; // error
y = x; // OK

但是,您可以在向下转换y时编写x = y as { a: 'a', b: 'b', c: 1 },这样错误就会消失。

对于您的第三个示例,{ a: 'a', b: 'b', c: 3, extraProp: 'no-issues' }InterfaceEverythingRequired的一个子类型,因此类型断言(向下转换)有效。在您的第四个示例中,{ a: 'a', b: 'b', extraProp: 'what?' }InterfaceEverythingRequired是不相关的类型(它们没有子类型、超类型关系In ),在这种情况下,TypeScript不允许向下转换。您的第四个示例与以下情况类似:

代码语言:javascript
运行
复制
let x: string;
let y: number;

x = y as string; // Type 'number' cannot be converted to type 'string'
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48925872

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档