如何泛型标注可接受含string[]子类型的联合类型的函数
解决TypeScript中processArray函数的泛型类型标注问题
需求说明
- 为
processArray函数添加泛型类型标注,无需显式列举具体联合类型 - 确保调用
processArray(arr1)、processArray(arr2)时无TypeScript错误,processArray(arr3)按预期报错 - 适配含十余种OpenAPI生成的联合类型的应用,未来新增类型无需修改类型定义
问题代码示例
function processArray<T extends string[]>(arr: T): void { console.log(arr); } const sArr = ["a", "b", "c"]; const nArr = [1, 2, 3]; const bArr = [true, false]; const arr1 = Math.random() < 0.5 ? sArr : nArr processArray(arr1); // 错误,但不应报错 const arr2 = Math.random() < 0.5 ? sArr : bArr processArray(arr2); // 错误,但不应报错 const arr3 = Math.random() < 0.5 ? nArr : bArr; processArray(arr3); // 预期报错,因为arr3不可能是string数组
解决方案
原代码的T extends string[]约束过于严格,仅接受纯string[]类型,无法兼容包含string[]分支的联合类型。我们可以通过判断类型与string[]是否存在交集来实现需求,无需显式列举任何具体类型:
function processArray<T>(arr: T extends {} ? (T & string[] extends never ? never : T) : never): void { console.log(arr); } const sArr = ["a", "b", "c"]; const nArr = [1, 2, 3]; const bArr = [true, false]; const arr1 = Math.random() < 0.5 ? sArr : nArr processArray(arr1); // 正常通过 const arr2 = Math.random() < 0.5 ? sArr : bArr processArray(arr2); // 正常通过 const arr3 = Math.random() < 0.5 ? nArr : bArr; processArray(arr3); // 预期报错:类型 'number[] | boolean[]' 的参数不能赋给类型 'never' 的参数
原理说明
T & string[] extends never:判断类型T与string[]是否没有交集。如果结果为true,说明T完全不可能是string[],将参数类型设为never触发报错;- 如果结果为
false,说明T包含string[]分支(或本身就是string[]),允许函数调用; - 该写法无需维护任何联合类型列表,未来新增的数组类型只要与
string[]有交集就会自动被兼容,完全适配需求。
内容的提问来源于stack exchange,提问作者xMort
相关产品推荐
相关产品推荐

