我有这个函数applyObject
,我想要输入属性。函数的参数是T
和V
,其中V
是函数的对象:
type V = { [key: string]: <R>(t: T) => R };
和T
是我想要在应用时V
的所有功能提供的类型。有没有办法做到这一点?
我认为使用映射类型是可能的,但我不确定。我这样想:
function applyObject<T, V extends { [key: string]: (t: T) => any }>(t: T, v: V) {
return Object.entries(v).reduce((applied, [_key, func]) => {
const key = _key as keyof V;
applied[key] = func(t);
return applied;
}, {} as {[P in keyof V]: Invoke<V[P]>}); // `Invoke` doesn't exist
}
const applied = applyObject(
{ one: 1, two: 'something' },
{ a: t => t.one, b: t => t.two }
);
applied.a; // should give intellisense as number
applied.b // should give intellisense as string
答案 0 :(得分:2)
这个怎么样:
type V<T, A> = {[K in keyof A]: (t: T) => A[K]};
function applyObject<T, A extends any>(t: T, v: V<T, A>): A {
const ret = {} as A;
for (const k in v) {
ret[k] = v[k](t);
}
return ret;
}
const applied = applyObject(
{ one: 1, two: 'something' },
{ a: t => t.one, b: t => t.two }
); // inferred as {a: number, b: string}
我们的想法是根据输入对象类型V
表达T
类型,以及A
的预期返回值类型applyObject()
。 V<T,A>
的键与A
的键相同,值是从T
到相应属性类型A
的函数。此定义允许您使用inference from mapped types键入applyObject()
。
(这里有一点需要注意。如果你看到,我将A
中的applyObject()
参数定义为A extends any
。这不是必需的;每种类型都延伸{{1在TypeScript中。但如果没有它,any
会被推断为A
,这并不是特别有用。我不知道为什么{a: any, b: any}
修复它,但确实如此。有人更熟悉TypeScript类型推断的细节有什么想法?)
我还修改了实现,因为我更容易说服TypeScript它是类型安全的。如果您可以使TypeScript满意或强迫它沉默,请随意使用您自己的实现。
无论如何,希望有所帮助。祝你好运!