如何在TypeScript编译时检查省略?



我不明白为什么这段代码在使用省略实用程序类型时可以工作:

type Foo = {
prop1: string;
prop2: string;
}
const foo: Foo = {
prop1: 'prop1',
prop2: 'prop2'
}
console.log(foo) // {"prop1": "prop1", "prop2": "prop2"}
type Bar = Omit<Foo, 'prop2'> & {
prop3: string;
}
const bar: Bar = {
...foo,
prop3: 'prop3'
}
console.log(bar) // {"prop1": "prop1", "prop2": "prop2", "prop3": "prop3"}

同时,直接使用Bar如预期的那样失败:

const qux: Bar = {
prop1: "prop1",
prop2: "prop2", // '{ prop1: string; prop2: string; prop3: string; }' is not assignable to type 'Bar'
prop3: "prop3"
}

这是因为过多的属性检查只发生在对象字面量中的属性上,而且只在某些情况下发生。多余的属性实际上不是类型安全问题;编译器只有在认为代码可能会立即忘记它们时才会发出警告。像const x: {a: string} = {a: "", b: ""}这样的东西是一个问题,因为没有什么能安全地访问b属性。但const y = {a: "", b: ""}; const x: {a: string} = y;是好的,因为y记得b,即使x忘记了。

同样,一般来说,额外的属性不是类型安全问题。你希望编译器允许额外的属性,否则接口扩展将无法工作(如果interface Foo {a: string}interface Bar extends Foo {b: string},那么禁止额外的属性将意味着BarFoo不兼容,并且TypeScript的结构类型系统将被击败)。TypeScript并没有真正的"精确类型"。就像《Flow》一样。有一个开放的请求在微软/打印稿# 12936支持的类型,但是现在我们没有他们。我们所拥有的只是结构子类型,其中{a: string, b: string}可分配给{a: string},以及在非常特殊的情况下有时会发出警告的多余属性检查。


bar的初始化项中,您正在传播foo,一个已经存在的变量。它不是对象字面量,因此没有多余的属性检查。这是按照ms/TS#41237的预期工作。

另一方面,qux的初始化器直接在对象字面量中添加了多余的属性,这会发出警告,因为没有人会记住quxprop2属性。

最新更新