我用两个函数创建了一个简单的映射,这些函数带有一个'foo:string'参数,并实现了直接返回的各种函数:
import { mapValues } from 'lodash';
const fun1 = (foo: string) => (name: string, surname: string) => {};
const fun2 = (foo: string) => (age: number) => {};
interface Actions {
fun1: typeof fun1;
fun2: typeof fun2;
}
const actions: Actions = { fun1, fun2 };
const mappedActions = mapValues(actions, action => action('bar'));
mappedActions.fun1(1);
使用mapValues
,我遍历这些函数,并使用一些公共参数调用它们。我期望的是mappedActions
映射中分配的半调用函数的映射,但是类型仍然存在问题。
fun1
不能解析为具有(name: string, surname: string)
参数,但仍是顶层参数的函数。
我应该如何构成才能使TypeScript正确解析类型?
答案 0 :(得分:2)
我将您的代码段复制到了CodeSandbox,并分析了Lodash的功能mapValues()
,我认为mapValues()
的类型与您的目的不符。
mapValues<T extends object, TResult>(obj: T | null | undefined, callback: ObjectIterator<T, TResult>): { [P in keyof T]: TResult };
如您所见,函数mapValues接受一个对象(T extends object
),并为此对象的每个键分配TResult
,这样:
mapValues<Actions, ((name: string, surname: string) => void) | ((age: number) => void)>(obj: Actions, callback: ObjectIterator<Actions, ((name: string, surname: string) => void) | ((age: number) => void)>): {
我尝试将lodash(尤其是 lodash / fp )与TypeScript结合使用,我可以说并非所有功能都能完美运行,也很难为所有可能性创建通用类型
答案 1 :(得分:1)
我想我找到了一种正确解析类型的方法:
import { mapValues } from 'lodash';
const fun1 = (foo: string) => (name: string, surname: string) => {};
const fun2 = (foo: string) => (age: number) => {};
type FunctionDictionary = { [id: string]: ((...args: any[]) => any) };
interface Actions extends FunctionDictionary {
fun1: typeof fun1;
fun2: typeof fun2;
}
const actions: Actions = { fun1, fun2 };
type ReturnTypeDict<T> = T extends { [id: string]: ((...args: any[]) => any) } ? {
[P in keyof T]: ReturnType<T[P]>;
} : never;
const map: (actions: Actions) => ReturnTypeDict<Actions> = actions => {
return mapValues(actions, action => action('bar')) as ReturnTypeDict<Actions>;
}
const mappedActions = map(actions);
mappedActions.fun1(1);
此处的键是ReturnType条件类型。为了使用它,您必须创建自己的条件类型:
type ReturnTypeDict<T> = T extends { [id: string]: ((...args: any[]) => any) } ? {
[P in keyof T]: ReturnType<T[P]>;
} : never;
现在您必须明确地说您的接口扩展了所需的字典类型:
type FunctionDictionary = { [id: string]: ((...args: any[]) => any) };
interface Actions extends FunctionDictionary {
fun1: typeof fun1;
fun2: typeof fun2;
}
然后创建一个可以正确映射数据的函数:
const map: (actions: Actions) => ReturnTypeDict<Actions> = actions => {
return mapValues(actions, action => action('bar')) as ReturnTypeDict<Actions>;
}