下面的泛型函数接受一个函数对象,并返回一个具有相同propnames的对象,该对象的值与相应函数的返回值相同 .
const combineValues = obj => {
const res = {};
for (const k in obj){
res[k] = obj[k]()
}
return res;
}
const combined = combineValues({
n: () => 1,
s: () => 's'
}); // { n: 1, s: 's' }
尝试在Typescript中为此函数定义签名和实现
const combineValues =
<K extends string> (obj: Record<K, () => any>): Record < K, any > => {
const res = {} as Record<K, any>;
for (const k in obj){
res[k] = obj[k]()
}
return res;
}
const combined = combineValues({
n, s
}) // Record<"n" | "s", any>
但 combined
不保留值的原始类型
const combcombineValues = <K extends string, T>(obj: Record<K, () => T>): Record<K, T> => {
const res = {} as Record<K, T>;
for (const k in obj){
res[k] = obj[k]()
}
return res;
}
仅当所有函数道具返回相同类型时才有效 T
是否可以在Typescript中完全定义它?
2 回答
这可以在当前版本的TypeScript(v2.7)中完成,无需等待条件类型,使用inference from mapped types,TypeScript的一个功能,其中函数可以从输出到输入推断类似于"backwards"方向的类型 .
首先让我们定义映射类型
Funcs<T>
,它接受一个普通对象并将其转换为一个对象,其属性是返回普通对象的属性类型的所有函数:请注意这种类型基本上是您想要做的事情的倒退 . 现在让我们输入
combineValues()
:正如您所看到的,它将
Funcs<T>
作为输入并返回T
作为输出 . 让我们看看它是否有效:这几乎就是你想要的 . 唯一的区别是TypeScript倾向于将
() => 1
解释为返回number
的函数,而不是返回文字1
的函数 . 你可以做些什么来解决这个问题;最简单的(虽然有点重复)是断言返回类型文字:希望有所帮助 . 祝好运!
更新:注意到编译器似乎在TypeScript 2.7中键入
combined
为{n: any, s: any}
. 幸运的是,当您使用Intellisense检查类型时,这似乎只会发生,正如(我认为)在Microsoft/TypeScript#14041中所述 . 如果您实际使用该值,您将看到它具有正确的类型:Playground link
所以,我想我坚持这个答案,虽然Intellisense错误是不幸的 . 祝你好运!
您可以使用conditional types(在编写本文时尚未发布的2.8版本,在
npm install -g typescript@next
中计划用于March release)来获取此类型的原型2.8 .