为何TypeScript期望交叉类型而非联合类型?示例解析
为什么TypeScript期望交叉类型而非联合类型?
问题根源
当你把FNS[id]赋值给变量fn时,TypeScript会将fn的类型推断为所有对应函数的联合类型:((arg: { name: string }) => string) | ((arg: { name2: string }) => string)。
对于联合类型的函数,TypeScript在调用时会要求传入的参数必须满足所有函数参数的交叉类型——因为它无法确定你实际调用的是联合中的哪一个函数,只能接受所有函数都能兼容的参数(也就是{ name: string } & { name2: string }),这就是报错的核心原因。
而你调用t函数时类型提示正确,是因为泛型T和payload的类型在调用阶段是一一绑定的,但在函数内部把FNS[id]赋值给变量后,这种类型关联性就丢失了。
解决方案
方案1:直接调用,避免中间变量
不需要把FNS[id]赋值给单独变量,直接调用就能让TypeScript保持类型关联性:
export type FunctionsList = { HI: (arg: { name: string }) => string HELLO: (arg: { name2: string }) => string } export const FNS: FunctionsList = { HI: (arg) => arg.name, HELLO: (arg) => arg.name2 } function t<T extends keyof FunctionsList>(id: T, payload: Parameters<FunctionsList[T]>[0]) { return FNS[id](payload); // 直接调用,TS能正确匹配类型 } // 调用示例:类型提示正常,无报错 t("HI", { name: "Alice" }); t("HELLO", { name2: "Bob" });
方案2:显式断言类型(需保留中间变量时)
如果必须使用中间变量,可以通过类型断言告诉TSfn的具体类型是FunctionsList[T],而非联合类型:
function t<T extends keyof FunctionsList>(id: T, payload: Parameters<FunctionsList[T]>[0]) { const fn = FNS[id] as FunctionsList[T]; return fn(payload); }
补充:原泛型写法的问题
你原来的写法中额外定义了R extends Parameters<FunctionsList[T]>[0],这属于冗余约束——TypeScript无法将R和fn的参数类型建立强关联,反而会模糊类型推断逻辑。直接用Parameters<FunctionsList[T]>[0]作为payload的类型更直接清晰。
内容的提问来源于stack exchange,提问作者Marat Abdulin
相关产品推荐
相关产品推荐

