[Typescript] Creating Chainable Method Abstractions with Generics and the Builder Pattern - 05

import { expect, it } from "vitest";
import { fetchUser } from "fake-external-lib";

type Middleware<TInput, TOutput> = (input: TInput) => TOutput;

class DynamicMiddleware<TInput, TOutput> {
  private middleware: Middleware<any, any>[] = [];

  constructor(firstMiddleware: Middleware<TInput, TOutput>) {
    this.middleware.push(firstMiddleware);
  }

  // use middleware, the input should be previous step's output
  // the output of the middleware should be new, using genric
  // the outptu of the middleware will be the input of next middleware
  use<NewTOutput>(
    middleware: Middleware<TOutput, NewTOutput>
  ): DynamicMiddleware<TInput, NewTOutput> {
    this.middleware.push(middleware);

    return this as any;
  }

  async run(input: TInput): Promise<TOutput> {
    let result: TOutput = input as any;

    for (const middleware of this.middleware) {
      result = await middleware(result);
    }

    return result;
  }
}

const middleware = new DynamicMiddleware((req: Request) => {
  return {
    ...req,
    userId: req.url.split("/")[2],
  };
})
  .use((req) => {
    if (req.userId === "123") {
      throw new Error();
    }
    return req;
  })
  .use(async (req) => {
    return {
      ...req,
      user: await fetchUser(req.userId),
    };
  });

it("Should fail if the user id is 123", () => {
  expect(middleware.run({ url: "/user/123" } as Request)).rejects.toThrow();
});

it("Should return a request with a user", async () => {
  const result = await middleware.run({ url: "/user/matt" } as Request);

  expect(result.user.id).toBe("matt");
  expect(result.user.firstName).toBe("John");
  expect(result.user.lastName).toBe("Doe");
});

 

posted @   Zhentiw  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2021-02-15 [Node] Install packages correctly and avoid attacks
2020-02-15 【时间管理】猴子理论 ”monkey-on-the-back” Analogy
2020-02-15 【时间管理】GTD:Getting things done
2019-02-15 [Webpack] Create Separate webpack Configs for Development and Production with webpack-merge
2019-02-15 [Algorithm] Reverse array of Chars by word
2018-02-15 [Tools] Using mobile device for debugging your mobile web site
2018-02-15 [Tools] Create your own mobile emulator device by using Chrome dev tool
点击右上角即可分享
微信分享提示