TypeScript中如何从泛型回调数组正确推断返回联合类型?
解决TypeScript中createUnion函数的联合类型推断问题
问题根源
你当前的createUnion函数泛型定义为<Creation>,要求所有回调函数的返回类型都兼容Creation。当回调返回类型存在子类型关系时(比如string和null),TypeScript能自动推断出Creation为两者的联合类型;但当返回类型无直接子类型关系时(比如string和number),TypeScript无法找到公共兼容类型,会默认以第一个回调的返回类型作为Creation,导致后续回调类型不匹配报错。
修正方案
修改泛型定义,让TypeScript捕获数组中每个回调的具体类型,再提取所有返回类型的联合:
function createUnion<T extends (() => unknown)[]>(creators: [...T]): ReturnType<T[number]> { const index = Math.floor(Math.random() * creators.length); return creators[index](); }
关键改动说明
T extends (() => unknown)[]:泛型T约束为函数数组,捕获每个回调的具体类型[...T]:使用剩余元组语法,强制TypeScript推断数组中每个元素的精确类型,而非模糊的联合类型数组ReturnType<T[number]>:提取数组中所有函数的返回类型,自动组合为联合类型
验证修正结果
将修正后的函数替换原代码,所有测试用例都能正确推断联合类型:
function createNumber(): number { return 42; } function createString(): string { return 'Hello'; } function createNull(): null { return null; } function createUndefined(): undefined { return undefined; } function createBoolean(): boolean { return true; } // 正确推断为 string | null export const stringOrNull = createUnion([createString, createNull]); // 正确推断为 number | undefined export const numberOrUndefined = createUnion([createNumber, createUndefined]); // 正确推断为 string | number,无类型报错 export const stringOrNumber = createUnion([createString, createNumber]); // 正确推断为 number | string,无类型报错 export const numberOrString = createUnion([createNumber, createString]); // 正确推断为 number | boolean,无类型报错 export const numberOrBoolean = createUnion([createBoolean, createNumber]);
内容的提问来源于stack exchange,提问作者David Y. Stephenson
相关产品推荐
相关产品推荐

