You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

错误原因

  1. 原泛型定义T = R1 | R2只是默认值,TypeScript无法强制约束用户传入的T一定是R1 | R2,导致elem(类型T)无法安全赋值给R1或R2。
  2. 校验函数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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 15:05:17