Javascript 为什么不是';需要我的函数返回特定类型的t类型脚本?
我有一个通用的Javascript 为什么不是';需要我的函数返回特定类型的t类型脚本?,javascript,typescript,Javascript,Typescript,我有一个通用的Factory函数,它应该返回一个特定类型: type Factory<T> = () => T; interface Widget { creationTime: number; } const build: Factory<Widget> = () => { return { creationTime: Date.now(), foo: 'bar', }; }; 有没有办法让Typescript将相同的“严格
Factory
函数,它应该返回一个特定类型:
type Factory<T> = () => T;
interface Widget {
creationTime: number;
}
const build: Factory<Widget> = () => {
return {
creationTime: Date.now(),
foo: 'bar',
};
};
有没有办法让Typescript将相同的“严格性”分配给我的通用
工厂类型?Typescript中的对象类型通常不禁止额外的属性。它们是“开放的”或“可扩展的”,而不是“封闭的”或“精确的”(参见)。否则就不可能使用子类或接口扩展:
interface FooWidget extends Widget {
foo: string;
}
const f: FooWidget = { creationTime: 123, foo: "baz" };
const w: Widget = f; // okay
有时人们想要这种“精确”的类型,但它们并不是语言的一部分。相反,TypeScript所拥有的是,这只发生在非常特殊的情况下:当一个“新鲜”的对象文本被赋予一个不知道该对象文本中某些属性的类型时:
const x: Widget = { creationTime: 123, foo: "baz" }; // error, what's foo
如果尚未将对象文字指定给任何类型,则该对象文字为“新鲜”。x
和w
之间的唯一区别在于x
中的文字是“新鲜”的,并且禁止使用过多的属性,而w
中的文字是。。。UH“stale”,因为它已经被赋予类型FooWidget
由此看来,您的widgetFactory
应该会给出一个错误,因为您返回的对象文本没有在任何地方赋值。不幸的是,在这种情况下,新鲜度丧失了。有一个长期存在的问题,注意到这一点,并取决于一个非常古老的问题。当检查返回的类型是否与预期的返回类型兼容时,TypeScript会自动加宽返回的类型。。。新鲜感也会消失。看起来没人喜欢这个,但是。所以现在,它是什么
您已经有了一个解决方法:显式注释函数的返回类型。这不是特别令人满意,但它完成了工作
export const WidgetFactory1: Factory<Widget> = {
build: (): Widget => {
return {
creationTime: Date.now(),
foo: 'bar', // error!
};
},
};
导出常量WidgetFactory1:工厂={
构建:():小部件=>{
返回{
creationTime:Date.now(),
foo:'bar',//错误!
};
},
};
其他解决方法包括强制编译器计算精确的类型,这是可能的,但比您现在所做的要难看得多:
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',
};
},
});
const exactWidgetFactory=
(
w:工厂)=>w;
导出常量WidgetFactory2=exactWidgetFactory({
生成:()=>{//错误!
// ~~~~~
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',
};
},
});