Rob*_*bin 5 javascript typescript
我有一个Factory应该返回特定类型的通用函数:
type Factory<T> = () => T;
interface Widget {
creationTime: number;
}
const build: Factory<Widget> = () => {
return {
creationTime: Date.now(),
foo: 'bar',
};
};
Run Code Online (Sandbox Code Playgroud)
我希望 Typescript 抛出错误,因为 foo它不是接口 Widget 上的属性。然而,事实并非如此。
但是如果我将widgetFactory函数修改为下面的代码——唯一的区别是我明确声明了返回类型——那么它确实会抛出一个错误:
const build: Factory<Widget> = (): Widget => {
return {
creationTime: Date.now(),
foo: 'bar',
};
};
Run Code Online (Sandbox Code Playgroud)
有没有办法让 Typescript 为我的泛型Factory类型分配相同的“严格性” ?
TypeScript 中的对象类型通常不会禁止额外的属性。它们是“开放的”或“可扩展的”,而不是“封闭的”或“精确的”(请参阅 microsoft/TypeScript#12936)。否则就不可能使用子类或接口扩展:
interface FooWidget extends Widget {
foo: string;
}
const f: FooWidget = { creationTime: 123, foo: "baz" };
const w: Widget = f; // okay
Run Code Online (Sandbox Code Playgroud)
有时人们想要这种“精确”的类型,但它们实际上并不是语言的一部分。相反,TypeScript 拥有的是过多的属性检查,这只发生在非常特殊的情况下:当给“新鲜”对象字面量一个不知道对象字面量中某些属性的类型时:
const x: Widget = { creationTime: 123, foo: "baz" }; // error, what's foo
Run Code Online (Sandbox Code Playgroud)
如果对象文字尚未分配给任何类型,则它是“新鲜的”。x和之间的唯一区别w是,在x字面上是“新鲜”的,并且禁止使用多余的属性,而在w字面上是...呃...“陈旧”,因为它已经被赋予了类型FooWidget。
由此看来,您似乎widgetFactory应该给出错误,因为您返回对象文字而不将其分配到任何地方。不幸的是,在这种情况下,新鲜感就消失了。有一个长期存在的问题microsoft/TypeScript#12632注意到了这一点,并且依赖于一个非常老的问题microsoft/TypeScript#241。当检查返回类型是否与预期返回类型兼容时,TypeScript 会自动加宽返回类型……并且新鲜感就会丢失。看起来没人喜欢这个,但是在不破坏其他东西的情况下很难修复它。所以目前来说,就是这样。
您已经有了一种解决方法:显式注释函数的返回类型。这并不是特别令人满意,但它完成了工作。
export const WidgetFactory1: Factory<Widget> = {
build: (): Widget => {
return {
creationTime: Date.now(),
foo: 'bar', // error!
};
},
};
Run Code Online (Sandbox Code Playgroud)
其他涉及尝试强制编译器计算精确类型的解决方法也是可能的,但比您正在做的要丑陋得多:
const exactWidgetFactory =
<W extends Widget & Record<Exclude<keyof W, keyof Widget>, never>>(
w: Factory<W>) => w;
export const WidgetFactory2 = exactWidgetFactory({
build: () => { // error!
// ~~~~~ <-- types of property foo are incompatible
return {
creationTime: Date.now(),
foo: 'bar',
};
},
});
Run Code Online (Sandbox Code Playgroud)
所以我建议继续你现有的事情。
| 归档时间: |
|
| 查看次数: |
91 次 |
| 最近记录: |