如何通过元组与重载基于函数输入设置TypeScript返回值类型?
解决方案
问题根源
你当前的实现中,中央库的useEventUtil泛型T被设为整个联合元组AllowedPairs,导致T[1]解析为MockEventPayload1 | MockEventPayload2,返回的Dispatcher接受两种payload的联合类型,自然不会对不符合单一类型的输入报错。
方案1:基于元组联合的修复
调整中央库的函数,通过泛型约束和Extract类型提取与传入事件名匹配的元组,精准推断对应的payload类型:
中央库代码:
type Dispatcher<T> = (p: T) => boolean | undefined; export function useEventUtil< T extends [string, unknown], E extends T[0] >(name: E): Dispatcher<Extract<T, [E, unknown]>[1]> { return (payload) => { return true; }; }
开发者使用代码:
import { useEventUtil } from 'central-utils' import { AllowedPairs, MockEventTypes } from 'types-pkg' // 显式传入AllowedPairs作为泛型参数,TypeScript会根据name自动推断对应payload const eventUtil = useEventUtil<AllowedPairs>(MockEventTypes.MockEventType1) eventUtil({ name: 12 // 此时TS会报错:类型“number”的参数不能赋给类型“string”的参数 })
方案2:改用Record类型映射(更直观易维护)
将事件类型与payload的对应关系改为Record结构,类型推断逻辑会更清晰:
有效类型包代码:
enum MockEventTypes { MockEventType1 = 'MockEventType1', MockEventType2 = 'MockEventType2', } interface MockEventPayload1 { name: string; } interface MockEventPayload2 { name: number; } // 用Record替代元组联合,直接映射事件到对应payload type EventPayloadMap = { [MockEventTypes.MockEventType1]: MockEventPayload1; [MockEventTypes.MockEventType2]: MockEventPayload2; };
中央库代码:
type Dispatcher<T> = (p: T) => boolean | undefined; export function useEventUtil< M extends Record<string, unknown>, E extends keyof M >(name: E): Dispatcher<M[E]> { return (payload) => { return true; }; }
开发者使用代码:
import { useEventUtil } from 'central-utils' import { EventPayloadMap, MockEventTypes } from 'types-pkg' const eventUtil = useEventUtil<EventPayloadMap>(MockEventTypes.MockEventType1) eventUtil({ name: 12 // TS报错:类型“number”不符合MockEventPayload1的name类型string })
两种方案都能实现你预期的类型校验,方案2的Record结构更符合TypeScript的类型映射习惯,后续扩展事件类型时也更易维护。
内容的提问来源于stack exchange,提问作者RPK_WRK
相关产品推荐
相关产品推荐

