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

借助TypeScript 2.8的Exclude类型优化partition函数类型

优化TypeScript中partition函数的类型定义(利用TS 2.8条件类型)

嘿,这个需求太赞了!TypeScript 2.8引入的条件类型(尤其是Exclude)确实能让partition函数的类型推断变得更精准,不再让返回的两个数组都只能是笼统的T[]。咱们一步步来实现这个优化:

问题分析

原来的partition类型定义:

function partition<T>(list: T[], predicate:(x:T)=>boolean): [T[],T[]];

不管谓词逻辑如何,返回的两个数组都只能被推断为T[]。比如如果传入一个number | string的联合类型数组,你没办法直接从返回值里得到“纯数字数组”和“纯字符串数组”的类型,只能靠后续类型断言,不够优雅。

优化方案:结合类型谓词与条件类型

我们可以通过函数重载+条件类型来实现精准的类型划分:

// 定义类型谓词的类型,约束能判断元素子类型的谓词
type TypeGuardPredicate<T, U extends T> = (x: T) => x is U;

// 第一个重载:针对使用类型谓词的场景,返回精准划分后的数组类型
function partition<T, U extends T>(
  list: T[],
  predicate: TypeGuardPredicate<T, U>
): [U[], Exclude<T, U>[]];

// 第二个重载:兼容原有普通boolean返回值的谓词调用,保持向后兼容
function partition<T>(
  list: T[],
  predicate: (x: T) => boolean
): [T[], T[]];

// 函数实现(类型宽松处理,重载已约束好类型规则)
function partition<T>(list: T[], predicate: (x: T) => any): [T[], T[]] {
  const pass: T[] = [];
  const fail: T[] = [];
  for (const item of list) {
    predicate(item) ? pass.push(item) : fail.push(item);
  }
  return [pass, fail];
}

效果演示

1. 联合类型数组的精准划分

这是最能体现优势的场景:

type MixedArrayItem = number | string | boolean;
const mixedList: MixedArrayItem[] = [1, "hello", true, 42, "world"];

// 使用类型谓词判断元素是否为number
const [numbers, nonNumbers] = partition(mixedList, (x): x is number => typeof x === "number");
// numbers 的类型是 number[]
// nonNumbers 的类型是 Exclude<MixedArrayItem, number>[] → (string | boolean)[]

2. 原有普通谓词调用的兼容性

如果你还是用普通的布尔返回值谓词,类型系统会自动回退到原有行为,完全兼容:

const [evens, odds] = partition([1,2,3,4], x => x % 2 === 0);
// evens 和 odds 的类型都是 number[],和原来的行为一致

原理说明

  • Exclude<T, U>是TS 2.8新增的条件类型,本质是T extends U ? never : T,用来从T中排除所有可赋值给U的类型。
  • 第一个重载利用类型谓词(x is U)让TypeScript能推断出哪些元素符合条件,再通过Exclude<T, U>得到不符合条件的元素类型,从而让返回值的类型更精准。
  • 重载的设计保证了原有代码无需修改就能正常工作,同时给需要精准类型的场景提供了支持。

内容的提问来源于stack exchange,提问作者Emmanuel Touzery

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:35:19