[英]How is Omit checked during compile time in TypeScript?
I'm failing to understand why this piece of code works when using the Omit utility type:我无法理解为什么在使用Omit实用程序类型时这段代码有效:
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"}
Meanwhile, using Bar
directly fails as expected:同时,按预期直接使用
Bar
失败:
const qux: Bar = {
prop1: "prop1",
prop2: "prop2", // '{ prop1: string; prop2: string; prop3: string; }' is not assignable to type 'Bar'
prop3: "prop3"
}
This happens because excess property checking only happens on properties in object literals, and only in some circumstances.发生这种情况是因为过多的属性检查只发生在对象字面量中的属性上,并且仅在某些情况下发生。 Excess properties are not really a type safety issue;
多余的属性并不是真正的类型安全问题; the compiler only warns about them if it thinks the code is likely to immediately forget about them.
编译器仅在认为代码可能立即忘记它们时才发出警告。 Something like
const x: {a: string} = {a: "", b: ""}
is a problem because nothing will be able to access that b
property safely.像
const x: {a: string} = {a: "", b: ""}
这样的东西是一个问题,因为没有任何东西能够安全地访问该b
属性。 But const y = {a: "", b: ""}; const x: {a: string} = y;
但是
const y = {a: "", b: ""}; const x: {a: string} = y;
const y = {a: "", b: ""}; const x: {a: string} = y;
is fine because y
remembers b
even if x
forgets it.很好,因为即使
x
忘记了, y
也会记住b
。
Again, in general, extra properties are not a type safety issue.同样,一般来说,额外的属性不是类型安全问题。 You want the compiler to allow extra properties, otherwise interface extension wouldn't work (if
interface Foo {a: string}
and interface Bar extends Foo {b: string}
, then forbidding extra properties would mean that Bar
is not compatible with Foo
, and TypeScript's structural type system would be defeated).您希望编译器允许额外的属性,否则接口扩展将不起作用(如果
interface Foo {a: string}
和interface Bar extends Foo {b: string}
,那么禁止额外的属性将意味着Bar
与Foo
不兼容,并且 TypeScript 的结构类型系统将被击败)。 TypeScript doesn't really have "exact types" the way Flow does. TypeScript 并不像 Flow 那样真正具有“精确类型”。 There's an open request at microsoft/TypeScript#12936 to support exact types, but right now we don't have them.
在microsoft/TypeScript#12936有一个开放的请求来支持精确类型,但现在我们没有它们。 All we have is structural subtyping where
{a: string, b: string}
is assignable to {a: string}
, and excess property checking which sometimes issues a warning about that, in very specific situations.我们所拥有的只是结构子类型,其中
{a: string, b: string}
可分配给{a: string}
,以及在非常特定的情况下有时会发出警告的过度属性检查。
In the initializer to bar
you are spreading foo
, an already-existing variable.在
bar
的初始化程序中,您正在传播foo
,一个已经存在的变量。 It's not an object literal, and therefore there is no excess property checking.它不是对象文字,因此没有多余的属性检查。 This is working as intended as per ms/TS#41237 .
这是按照ms/TS#41237的预期工作的。
On the other hand, your initializer for qux
is adding excess properties directly in an object literal, which does issue a warning, because nothing will remember that qux
has a prop2
property.另一方面,您的
qux
初始化程序直接在对象字面量中添加多余的属性,这确实会发出警告,因为没有人会记住qux
具有prop2
属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.