[Typescript] Builder pattern 07- Reducer
import {Expect, Equal} from "../types/utils"
import { expect, it } from 'vitest';
type PayloadsToDiscriminatedUnion<T extends Record<string, any>> = {
[K in keyof T]: { type: K } & T[K];
}[keyof T];
export class DynamicReducer<
TState,
TPayloadMap extends Record<string, any> = {}
> {
private handlers = {} as Record<
string,
(state: TState, payload: any) => TState
>;
addHandler<TType extends string, TPayload extends object>(
type: TType,
handler: (state: TState, payload: TPayload) => TState
): DynamicReducer<TState, TPayloadMap & Record<TType, TPayload>> {
this.handlers[type] = handler;
return this;
}
reduce(
state: TState,
action: PayloadsToDiscriminatedUnion<TPayloadMap>
): TState {
const handler = this.handlers[action.type];
if (!handler) {
return state;
}
return handler(state, action);
}
}
interface State {
username: string;
password: string;
}
const reducer = new DynamicReducer<State>()
.addHandler(
"LOG_IN",
(state, action: { username: string; password: string }) => {
return {
username: action.username,
password: action.password,
};
}
)
.addHandler("LOG_OUT", () => {
return {
username: "",
password: "",
};
})
.addHandler("UPDATE_USERNAME", (state, action: { username: string }) => {
return {
...state,
username: action.username,
};
});
it("Should return the new state after LOG_IN", () => {
const state = reducer.reduce(
{ username: "", password: "" },
{
type: "UPDATE_USERNAME",
username: "awdawdawd",
}
);
type test = [Expect<Equal<typeof state, State>>];
expect(state).toEqual({ username: "foo", password: "bar" });
});
it("Should return the new state after LOG_OUT", () => {
const state = reducer.reduce(
{ username: "foo", password: "bar" },
{ type: "LOG_OUT" }
);
type test = [Expect<Equal<typeof state, State>>];
expect(state).toEqual({ username: "", password: "" });
});
it("Should error if you pass it an incorrect action", () => {
const state = reducer.reduce(
{ username: "foo", password: "bar" },
{
// @ts-expect-error
type: "NOT_ALLOWED",
}
);
});
it("Should error if you pass an incorrect payload", () => {
const state = reducer.reduce(
{ username: "foo", password: "bar" },
// @ts-expect-error
{
type: "LOG_IN",
}
);
});
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2020-05-07 [React] useMemo and React.memo
2020-05-07 [Functional Programming] Coding Monoids with real task
2019-05-07 [React] Always useMemo your context value
2019-05-07 [Functional Programming] Examples: When and Unless
2019-05-07 [Algorithm] Modular exponentiation - using Recursion
2019-05-07 [Angular 8] Take away: Web Components with Angular Elements: Beyond the Basics
2018-05-07 [React] Forward a DOM reference to another Component using forwardRef in React 16.3