【发布时间】:2020-10-19 23:36:00
【问题描述】:
有没有办法让它不编译? (因为它确实......)
const bar: { a: string } = {
a: '',
...{b: ''}
}
【问题讨论】:
标签: typescript typescript-typings
有没有办法让它不编译? (因为它确实......)
const bar: { a: string } = {
a: '',
...{b: ''}
}
【问题讨论】:
标签: typescript typescript-typings
我震惊地发现它通过了类型检查器!
经过一番探索,我对为什么会发生这种情况有一种强烈的预感,但我还没有找到任何官方消息来支持它。 因此,这不是一个答案,而是一个对于评论来说太长的对话启动器。 就是这么说,接下来的事情要持保留态度。
我怀疑 TypeScript 的“归属”/“注释”机制允许基于子类型的一些回旋余地。 具体来说,当我们写:
const foo: Foo = bar;
只要bar 的类型是Foo 的子类型,这似乎就能顺利通过检查。
这是一个具体的例子:
class Foo {
public a: string;
}
// `Bar` is a subtype of `Foo`
class Bar extends Foo {
public b: string;
}
const foo: Foo = new Bar();
// ^^^ ^^^ This is just fine!
此外,由于 TypeScript 的子类型概念是“结构化的”,因此以下内容也是完全可以接受的:
class Foo {
a: string;
}
// `Quux` is structurally the same as (and therefore a subtype of) `Foo`
class Quux {
a: string;
}
const foo: Foo = new Quux();
考虑到这个[理论],检查器会接受您的示例,因为{ a: string; b: string } 是{ a: string } 的子类型。
总之,如果这是正确的,我认为没有办法诱使类型检查器拒绝您的示例。
编辑:这不是完整的故事。 正如@apflieger 指出的那样,这个理论并不能解释原因
const foo: { a: string } = {
a: 'test',
b: 'test',
};
被拒绝。 看起来传播在这里很关键。
可能是那种
{
a: 'test',
...{ b: 'test' }
}
推断为{ a: string } & { b: string },而在前一种情况下推断为{ a: string; b: string }。
【讨论】:
{ b: '' }。