TypeScript:如何从联合类型动态提取函数泛型并生成foo函数?
问题描述
我们定义了如下TypeScript类型与工具函数:
type FooParams <Params extends unknown[], Result> = { name: string, request: (...params: Params) => Promise<Result> } const foo = <Params extends unknown[], Result>(params: FooParams<Params, Result>) => { // 内部逻辑 }
同时有Todo接口、请求函数及存储请求的requestStore:
interface Todo { id: number; title: string; } const getTodos: () => Promise<Todo[]> = () => Promise.resolve([{ id: 2, title: 'clean' }]); const getTodo: (id: number) => Promise<Todo> = (id: number) => Promise.resolve({ id, title: 'clean' }); const requestStore = { getTodo: { name: 'getTodo', request: getTodo, }, getTodos: { name: 'getTodos', request: getTodos, }, } as const;
手动调用foo(requestStore['getTodo'])可以正常工作,但通过以下动态方式创建对应foo函数时会出现类型错误:
// 报错信息: // Type '(() => Promise<Todo[]>) | ((id: number) => Promise<Todo>)' is not assignable to type '() => Promise<Todo[]>'. // Type '(id: number) => Promise<Todo>' is not assignable to type '() => Promise<Todo[]>'.(2322) const createFooFromStore = (requestName: keyof typeof requestStore) => () => { const { name, request } = requestStore[requestName] foo({ name, request }) }
需要修改代码,为requestStore中的每个条目正确生成对应的foo函数。
问题原因
当requestName为keyof typeof requestStore时,requestStore[requestName]的类型是两个请求对象的联合类型,此时request的类型是两个函数的联合类型。而foo要求传入的是具体某一个函数类型,而非联合类型,因此TypeScript的类型检查会失败。
解决方案
方案1:泛型约束实现类型收窄
将createFooFromStore定义为泛型函数,让TypeScript跟踪具体的键类型,从而正确推断对应请求的类型:
const createFooFromStore = <K extends keyof typeof requestStore>(requestName: K) => () => { const { name, request } = requestStore[requestName]; foo({ name, request }); // 类型推断正常 };
方案2:预先生成全量foo函数对象
如果需要一次性为所有请求生成对应foo函数,可以创建映射对象,利用TypeScript的映射类型自动推导:
type FooStore = { [K in keyof typeof requestStore]: () => void; }; const fooStore: FooStore = Object.fromEntries( Object.entries(requestStore).map(([key, value]) => [ key, () => foo(value) ]) ) as FooStore; // 使用示例 fooStore.getTodo(); fooStore.getTodos();
两种方案都能让TypeScript正确识别每个请求的具体类型,避免联合类型导致的类型错误。
内容的提问来源于stack exchange,提问作者August P
相关产品推荐
相关产品推荐

