我正在尝试在 TypeScript 中声明一个fun
函数,该函数使用其类型参数T
作为哪些键可以用作另一个函数context.Foo
参数的约束:
interface Context<T> {
Foo(key: keyof T)
}
function fun<T>(provider: (context: Context<T>) => T): number {
return 1
}
fun<{a: number}>(context => {
return {a: context.Foo('a')}
})
到目前为止一切顺利,我只能在底部的foo
调用中使用"a"文字作为context.Foo
的key
参数,因为此调用有一个类型参数,该参数声明T
{a: number}
。
困扰我的是,我实际上将这种类型的结构内联定义为provider
函数体。我只能返回与定义匹配{a: number}
对象。
我想实现的是摆脱在调用时显式定义T
类型的fun
的需要,并让类型推断通过我从fun
的参数返回的对象的结构自行计算出此类型(需要T
), 喜欢这个:
fun(context => {
return {a: context.Foo('a')}
})
不幸的是,这以错误结束:
TS2345:类型"a"的参数不可分配给类型为"从不"的参数。
T
的类型推断失败并回退到never
在这种情况下绝对没有用。
是否可以以不需要显式设置fun
T
的方式定义此函数?
我认为没有任何方法可以实现这一点,一旦您尝试将Context<T>
与结果的键相关联,编译器就会放弃推理。
由于Foo
总是返回相同的值类型(至少从我在注释中的理解来看),您可以只指定该类型的键,而不必指定整个类型:
interface Context<K> {
Foo(key: K): number;
}
function fun<K extends string>(provider: (context: Context<K>) => Record<K, number>): Record<K, number> {
return provider(null as any);
}
let a = fun<'a'>(context => {
return { a: context.Foo('a') }
})