如何实现异构数组中match函数回调的类型收窄
让match函数的回调参数自动收窄到对应case类型
你当前的match函数因为泛型V是统一的顶层类型,导致每个回调的参数只能是V,没办法自动收窄到具体的case值类型。要实现你想要的类型收窄效果,需要调整类型定义和函数的泛型约束,让TypeScript能精确推导每个case的匹配值类型。
修改后的类型与函数实现
// 单个case的类型定义,K是匹配值的类型 type CaseItem<K> = | [K, (value: K) => void] | [K[], (value: K) => void]; // 定义match函数的泛型,Cases是所有case的联合类型 const match = <Cases extends CaseItem<any>[]>( value: Cases[number] extends CaseItem<infer K> ? K : never, cases: readonly [...Cases] ) => { for (const [key, func] of cases) { if (Array.isArray(key)) { if ((key as unknown[]).includes(value)) { return func(value as Cases[number] extends CaseItem<infer K> ? K : never); } } else { if (key === value) { return func(value); } } } };
关键说明
- 精确绑定case类型:
CaseItem<K>让每个case单独绑定自己的匹配值类型K,不管是单个值还是数组,回调参数都对应K类型(数组场景下K会自动推导为元素的联合类型)。 - 泛型推导约束:函数泛型
Cases约束为CaseItem<any>[],通过条件类型推导出所有case匹配值的联合类型,作为value的类型约束,确保传入的value只能是case中存在的值。 - const断言的作用:调用时必须加上
as const,让TypeScript保留数组元素的字面量类型,避免自动拓宽为string这类宽泛类型,才能实现精确的类型收窄。
使用示例
const value: "something" | "other" | "thing" = "something"; match(value, [ [ "something", (v) => { // v的类型自动收窄为 "something" console.log(v.toUpperCase()); } ], [ ["other", "thing"], (v) => { // v的类型自动收窄为 "other" | "thing" if (v === "other") { console.log("it's other"); } else { console.log("it's thing"); } } ] ] as const);
内容的提问来源于stack exchange,提问作者malobre
相关产品推荐
相关产品推荐

