不,这是不可能的。
microsoft/TypeScript#30120 的问题要求一种用泛型类型注释已声明变量的方法,其中编译器应该推断泛型类型参数而不是需要手动指定。此问题已作为 microsoft/TypeScript#26242 的副本关闭,该提案支持“部分类型参数推断”,这将解决更普遍的问题,即让开发人员在目前唯一的解决方案是手动的情况下要求编译器推断类型参数规格。正如您所注意到的,generic parameter defaults not 解决了这个问题:虽然默认值(如 <T = any>)允许您省略类型参数,但编译器不会推断任何东西当你这样做的时候;它只是将省略的参数替换为默认值。
如果实现了 microsoft/TypeScript#26242,则可能会编写如下内容:
// ⚠ NOT VALID TYPESCRIPT, DO NOT USE ⚠
const thing: RenderObject<infer> = {
meta: { foo: 'bar' },
render: (meta) => <i>{meta.foo}</i>,
};
但现在你不能。 GitHub 问题是开放的,但已经存在了一段时间,最近没有任何明显的动向。我不知道这是否重要,但如果你强烈认为应该支持它,你可能想去那个问题并给它一个?,或者如果你认为它特别重要,请描述你的用例与现有的相比,引人注目。
如果没有此类支持,您为获得这种行为所做的任何事情都将是一种解决方法。
我通常提倡的解决方法是使用辅助函数,因为调用泛型函数是编译器实际为您推断类型参数的地方之一:
const asRenderObject = <T,>(x: RenderObject<T>) => x;
const thing = asRenderObject({
meta: { foo: 'bar' },
render: (meta) => <i>{meta.foo}</i>,
})
/* const thing: RenderObject<{
foo: string;
}> */
这相当优雅,或者至少可以说和RenderObject<infer> 一样优雅。你得到你想要的类型而没有多余的规范。缺点是在运行时,您有一个额外的函数调用。只有您才能真正知道在此处添加调用是否会对代码的运行时性能产生任何明显影响。我对此有点怀疑,因为这意味着您在很短的时间内创建了数千个这样的对象......如果是这样,您可能希望在担心之前考虑重构以提高运行时性能关于 TypeScript 类型推断。从现在开始,我会理所当然地认为额外的函数调用是不可接受的。
此时我能想到的唯一其他解决方法是手动指定类型;通过注释变量声明:
interface Thang { foo: string }
const thing: RenderObject<Thang> = {
meta: { foo: 'bar' },
render: (meta) => <i>{meta.foo}</i>,
};
或通过让编译器推断变量类型,但注释render 回调参数(因为编译器无处可指向type it contextually):
interface Thang { foo: string }
const thing3 = {
meta: { foo: 'bar' },
render: (meta: Thang) => <i>{meta.foo}</i>,
};
但是现在根本没有发生类型参数推断......这个“解决方法”是为了完全避免这个问题。
那么,就这样吧。直到并且除非microsoft/TypeScript#26242 或类似的实现,没有办法做你所要求的。对不起!
Playground link to code