TypeScript实现partition函数遇类型错误,求助修复方案
TypeScript partition函数类型错误修复方案
问题描述
我从StackOverflow获取了一个partition函数,想要用TypeScript实现,但遇到类型问题:函数接收多类型数组(type DataItem = InputItem | CheckboxItem;),返回由泛型指定的InputItem[]和CheckboxItem[]组成的数组,但在reduce方法中出现TS错误:'R1' could be instantiated with an arbitrary type which could be unrelated to 'R1 | T'.(2345)。
原代码如下:
function partition<R1, R2, T = R1 | R2>( array: T[], isValid: (element: T) => boolean ): [R1[], R2[]] { const result = array.reduce<[R1[], R2[]]>( ([pass, fail], elem) => { return isValid(elem) ? [[...pass, elem], fail] : [pass, [...fail, elem]]; }, [[], []] ); return result; } type InputItem = { type: 'input'; label: string; value: string; }; type CheckboxItem = { type: 'checkbox'; label: string; value: boolean; }; type DataItem = InputItem | CheckboxItem; const data: DataItem[] = [ { type: 'input', label: 'Input 1', value: '' }, { type: 'checkbox', label: 'Checkbox 1', value: true }, ]; const [checkboxes, inputs] = partition<CheckboxItem, InputItem>( data, (item) => item.type === 'checkbox' ); console.log('checkboxes:', checkboxes); console.log('inputs:', inputs);
错误原因
- 原泛型定义
T = R1 | R2只是默认值,TypeScript无法强制约束用户传入的T一定是R1 | R2,导致elem(类型T)无法安全赋值给R1或R2。 - 校验函数
isValid仅返回boolean,TypeScript无法识别符合条件的元素就是R1类型,不符合的是R2类型,无法建立类型关联。
修复方案
调整泛型约束并使用类型守卫,让TypeScript明确校验函数的返回值对应的元素类型,同时约束R1和R2与T的关系:
function partition<T, R1 extends T>( array: T[], isValid: (element: T) => element is R1 ): [R1[], Exclude<T, R1>[]] { return array.reduce( ([pass, fail], elem) => { return isValid(elem) ? [[...pass, elem], fail] : [pass, [...fail, elem]]; }, [[], []] as [R1[], Exclude<T, R1>[]] ); } type InputItem = { type: 'input'; label: string; value: string; }; type CheckboxItem = { type: 'checkbox'; label: string; value: boolean; }; type DataItem = InputItem | CheckboxItem; const data: DataItem[] = [ { type: 'input', label: 'Input 1', value: '' }, { type: 'checkbox', label: 'Checkbox 1', value: true }, ]; // 无需手动指定泛型,TypeScript会自动推导 const [checkboxes, inputs] = partition( data, (item): item is CheckboxItem => item.type === 'checkbox' ); console.log('checkboxes:', checkboxes); // 类型为CheckboxItem[] console.log('inputs:', inputs); // 类型为InputItem[]
关键改动说明
- 泛型调整为
partition<T, R1 extends T>:明确R1是T的子类型,R2通过Exclude<T, R1>自动推导,无需手动传入。 - 校验函数改为
(element: T) => element is R1:使用类型守卫,告诉TypeScript当函数返回true时,element的类型是R1。 - 初始值添加类型断言
as [R1[], Exclude<T, R1>[]]:帮助TypeScript识别reduce的初始值类型,避免类型推断错误。 - 调用时无需手动指定泛型:TypeScript会根据输入数组和类型守卫自动推导
R1和R2的类型。
内容的提问来源于stack exchange,提问作者acidernt
相关产品推荐
相关产品推荐

