如何在TypeScript中实现Rust风格match函数并正确定义其类型
简化版Rust match语法的TypeScript类型实现
最终实现代码
export function match< // 约束匹配值的类型为字符串或数字字面量联合 T extends string | number, // 约束配置对象:key必须覆盖T的所有成员,value必须是无参函数 Options extends Record<T, () => unknown> >(value: T, options: Options): ReturnType<Options[T]> { // 类型断言安全,泛型约束已保证options[value]一定是符合要求的函数 return options[value]() as ReturnType<Options[T]> }
规则匹配说明
- 穷尽key检查:因为
Options被约束为Record<T, ...>,T是传入匹配值的所有可能类型的联合,如果配置对象缺少任意一个T中存在的key,TypeScript会直接抛出属性缺失错误。 - 函数类型校验:配置对象的value被约束为
() => unknown,如果传入非函数类型的值,TypeScript会抛出类型不匹配错误。 - 返回值类型自动推导:通过
ReturnType<Options[T]>自动聚合所有分支函数的返回值类型,返回值就是所有分支返回值的联合类型,无需手动声明。
效果验证
正常使用场景
const value = Math.random() > 0.5 ? 1 : 'foo' const result = match(value, { 1: () => 100, foo: () => 'F' }) // result 类型自动推导为 100 | 'F',符合预期
错误触发场景
- 缺少匹配key:
// 报错:类型 "{ 1: () => number; }" 缺少属性 "foo",类型 "Record<1 | "foo", () => unknown>" 需要该属性 const result = match(value, { 1: () => 100 })
- 配置项不是函数:
// 报错:不能将类型“number”分配给类型“() => unknown” const result = match(value, { 1: 100, foo: () => 'F' })
注意事项
原实现中使用了case作为参数名,case是JavaScript/TypeScript的保留关键字,会触发语法错误,因此实现中替换为了value作为参数名。
内容的提问来源于stack exchange,提问作者Argeento
相关产品推荐
相关产品推荐

