TypeScript泛型条件类型报错:createMapper函数类型不兼容问题排查
问题分析
你编写的createMapper函数类型定义符合需求,但实现阶段出现类型报错,核心原因是TypeScript编译器无法在函数内部将运行时的分支判断与编译时的泛型条件类型做精确关联。
当你返回source.map(mapper)或mapper(source)时,编译器仅能推断出返回值是Out | Out[],但你的返回类型是条件类型Source extends In[] ? Out[] : Out——这里的Source是未具体化的泛型参数,在函数实现阶段编译器无法确认当前分支对应的就是条件类型的某一种结果,因此抛出类型不兼容的错误。
修复方案1:类型断言(快速解决)
直接通过类型断言告诉编译器,我们的分支判断结果完全匹配条件类型的预期:
function createMapper<In, Out>( mapper: (input: In) => Out ): <Source extends In | In[]>(source: Source) => Source extends In[] ? Out[] : Out { return (source: Source) => Array.isArray(source) ? source.map(mapper) as Source extends In[] ? Out[] : Out : mapper(source) as Source extends In[] ? Out[] : Out; }
如果追求简洁,也可以直接断言为返回类型的整体:
function createMapper<In, Out>( mapper: (input: In) => Out ): <Source extends In | In[]>(source: Source) => Source extends In[] ? Out[] : Out { return ((source) => Array.isArray(source) ? source.map(mapper) : mapper(source)) as any; }
修复方案2:函数重载(更严谨)
若不想使用类型断言,可通过函数重载明确输入与输出的对应关系,让编译器自动推导类型:
function createMapper<In, Out>(mapper: (input: In) => Out) { function mapFn(source: In): Out; function mapFn(source: In[]): Out[]; function mapFn(source: In | In[]): Out | Out[] { return Array.isArray(source) ? source.map(mapper) : mapper(source); } return mapFn; }
测试示例
使用重载后的函数,你的需求场景能完美运行:
type MapI = { abc: 123 }; const mapI: MapI = { abc: 123 }; const mapps = createMapper((m: MapI) => m); const mappedArray = mapps(Array(3).fill(mapI)); console.log(mappedArray.length); // 编译器正确识别为数组 const mappedValue = mapps(mapI); console.log(mappedValue.abc); // 编译器正确识别为对象
内容的提问来源于stack exchange,提问作者IamCracker
相关产品推荐
相关产品推荐

