我有一个泛型Factory
函数,它应该返回一个特定的类型:
type Factory<T> = () => T;
interface Widget {
creationTime: number;
}
const build: Factory<Widget> = () => {
return {
creationTime: Date.now(),
foo: 'bar',
};
};
我希望Typescript会抛出一个错误,因为foo
不是接口Widget上的属性。
但是如果我将widgetFactory
函数修改为下面的代码--唯一的区别是我显式声明了返回类型--那么它确实会抛出一个错误:
const build: Factory<Widget> = (): Widget => {
return {
creationTime: Date.now(),
foo: 'bar',
};
};
有没有办法让Typescript为我的泛型Factory
类型分配相同的“严格性”?
1条答案
按热度按时间4sup72z81#
TypeScript中的对象类型通常不禁止额外的属性。它们是“开放的”或“可扩展的”,而不是“封闭的”或“精确的”(参见microsoft/TypeScript#12936)。否则将无法使用子类或接口扩展:
有时候,人们想要这样的“精确”类型,但它们并不是语言的一部分,相反,TypeScript有多余的属性检查,这只在非常特殊的情况下才会发生:当一个“新鲜的”对象文字被赋予一个不知道对象文字中某些属性的类型时:
对象常量是“新鲜的”,如果它还没有被赋给任何类型。
x
和w
之间的唯一区别是,在x
中,常量是“新鲜的”,并且禁止多余的属性,而在w
中,常量是...呃...“陈旧的”,因为它已经被赋给了FooWidget
类型。这样看来,
widgetFactory
应该会给予一个错误,因为您返回的是object literal,而没有将其赋给任何地方。不幸的是,在这种情况下,新鲜度丢失了。有一个长期存在的问题microsoft/TypeScript#12632注意到了这一点,并且依赖于一个非常老的问题,microsoft/TypeScript#241.TypeScript在检查返回类型是否与预期的返回类型兼容时会自动加宽返回类型...并且新鲜度会丢失。看起来没有人喜欢这样,但要想修好它而不破坏其他东西是很难的。所以现在,它就是这样。您已经有一个解决方法:显式注解函数的返回类型。这不是特别令人满意,但它完成了任务。
其他尝试强制编译器计算精确类型的变通方法也是可行的,但比您现在所做的要糟糕得多:
所以我建议你继续做你手头的事。
Playground代码链接