为之则易,不为|

Code_You

临河而羡鱼,不如归家结网。

[TypeScript] 实现一个强大的模式匹配

前言

众所不周知,在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"

本文作者:Code_You

本文链接:https://www.cnblogs.com/coderDemo/p/18669554

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   demo_you  阅读(6)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示