前言
众所不周知,在 Rust 语言中,有一个强大的语法,模式匹配:
fn main() {
let data = Some(12);
match data {
Some(i) => println!("{}", i),
None => println!("No data"),
}
}
那么在 typescript 中我们如何为自己实现一个这么好用的语法呢?
match.ts
export type MatchModel<T, R> = Array<
[((value: T) => boolean) | T, (value: T) => R]
>;
// 定义 Match 类来处理模式匹配
class Match<T> {
private readonly value: T;
constructor(value: T) {
this.value = value;
}
// with 方法用于定义匹配分支
with<R>(patterns: Array<[((value: T) => boolean) | T, (value: T) => R]>): R {
for (const [pattern, handler] of patterns) {
if (
typeof pattern === "function"
? (pattern as (value: T) => boolean)(this.value)
: pattern === this.value
) {
return handler(this.value);
}
}
throw new Error("No pattern matched");
}
}
// 创建 match 函数作为入口
export function match<T>(value: T): Match<T> {
return new Match(value);
}
usage1
基础数值匹配
const numberModel: MatchModel<number, string> = [
[1, n => `one: ${n}`],
[2, n => `two: ${n}`],
[3, n => `three: ${n}`],
[n => n > 3, n => `more than three: ${n}`],
];
console.log(match(1).with(numberModel)); // "one: 1"
console.log(match(100).with(numberModel)); // "more than three: 100"
usage2
自定义类型匹配
type Result<T, E = Error> = {
error?: E;
value?: T;
};
type ResultModel<T, E = Error> = [
(result: Result<T, E>) => boolean,
(result: Result<T, E>) => string
];
const resultModel: ResultModel<number>[] = [
[r => !r.error, r => `Success: ${r.value}`],
[r => !!r.error, r => `Error: ${r.error}`],
];
console.log(match({ value: 42 }).with(resultModel)); // "Success: 42"
console.log(
match({ error: new Error("Something went wrong") }).with(resultModel)
); // "Error: Error: Something went wrong"
usage3
枚举匹配
enum Color {
Red,
Green,
Blue,
}
const colorModel: MatchModel<Color, string> = [
[Color.Red, () => "Found Red"],
[Color.Green, () => "Found Green"],
[Color.Blue, () => "Found Blue"],
];
console.log(match(Color.Green).with(colorModel)); // "Found Green"
console.log(match(Color.Blue).with(colorModel)); // "Found Blue"