Skip to content

Commit dc00db3

Browse files
committed
Changed 34
1 parent 73a3c1d commit dc00db3

File tree

2 files changed

+29
-20
lines changed

2 files changed

+29
-20
lines changed

src/07-challenges/34-dynamic-reducer.problem.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { expect, it } from "vitest";
22
import { Equal, Expect } from "../helpers/type-utils";
33

44
// Clue - this will be needed!
5-
type HandlersToDiscriminatedUnion<T extends Record<string, any>> = {
5+
type PayloadsToDiscriminatedUnion<T extends Record<string, any>> = {
66
[K in keyof T]: { type: K } & T[K];
77
}[keyof T];
88

@@ -12,7 +12,7 @@ type HandlersToDiscriminatedUnion<T extends Record<string, any>> = {
1212
* | { type: "LOG_IN", username: string, password: string }
1313
* | { type: "LOG_OUT" }
1414
*/
15-
type TestingHandlersToDiscriminatedUnion = HandlersToDiscriminatedUnion<{
15+
type TestingPayloadsToDiscriminatedUnion = PayloadsToDiscriminatedUnion<{
1616
LOG_IN: { username: string; password: string };
1717
LOG_OUT: {};
1818
}>;
@@ -27,7 +27,7 @@ export class DynamicReducer {
2727

2828
addHandler(
2929
type: unknown,
30-
handler: (state: unknown, payload: unknown) => unknown,
30+
handler: (state: unknown, payload: unknown) => unknown
3131
): unknown {
3232
this.handlers[type] = handler;
3333

@@ -57,7 +57,7 @@ const reducer = new DynamicReducer<State>()
5757
username: action.username,
5858
password: action.password,
5959
};
60-
},
60+
}
6161
)
6262
.addHandler("LOG_OUT", () => {
6363
return {
@@ -69,7 +69,7 @@ const reducer = new DynamicReducer<State>()
6969
it("Should return the new state after LOG_IN", () => {
7070
const state = reducer.reduce(
7171
{ username: "", password: "" },
72-
{ type: "LOG_IN", username: "foo", password: "bar" },
72+
{ type: "LOG_IN", username: "foo", password: "bar" }
7373
);
7474

7575
type test = [Expect<Equal<typeof state, State>>];
@@ -80,7 +80,7 @@ it("Should return the new state after LOG_IN", () => {
8080
it("Should return the new state after LOG_OUT", () => {
8181
const state = reducer.reduce(
8282
{ username: "foo", password: "bar" },
83-
{ type: "LOG_OUT" },
83+
{ type: "LOG_OUT" }
8484
);
8585

8686
type test = [Expect<Equal<typeof state, State>>];
@@ -94,7 +94,7 @@ it("Should error if you pass it an incorrect action", () => {
9494
{
9595
// @ts-expect-error
9696
type: "NOT_ALLOWED",
97-
},
97+
}
9898
);
9999
});
100100

@@ -104,6 +104,6 @@ it("Should error if you pass an incorrect payload", () => {
104104
// @ts-expect-error
105105
{
106106
type: "LOG_IN",
107-
},
107+
}
108108
);
109109
});

src/07-challenges/34-dynamic-reducer.solution.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
import { expect, it } from "vitest";
22
import { Equal, Expect } from "../helpers/type-utils";
33

4-
type HandlersToDiscriminatedUnion<T extends Record<string, any>> = {
4+
type PayloadsToDiscriminatedUnion<T extends Record<string, any>> = {
55
[K in keyof T]: { type: K } & T[K];
66
}[keyof T];
77

88
export class DynamicReducer<
99
TState,
10-
THandlers extends Record<string, any> = {},
10+
TPayloadMap extends Record<string, any> = {}
1111
> {
1212
private handlers = {} as Record<
1313
string,
14-
(state: TState, action: HandlersToDiscriminatedUnion<THandlers>) => TState
14+
(state: TState, payload: any) => TState
1515
>;
1616

17-
addHandler<TType extends string, TPayload>(
17+
addHandler<TType extends string, TPayload extends object>(
1818
type: TType,
19-
handler: (state: TState, payload: TPayload) => TState,
20-
): DynamicReducer<TState, THandlers & Record<TType, TPayload>> {
19+
handler: (state: TState, payload: TPayload) => TState
20+
): DynamicReducer<TState, TPayloadMap & Record<TType, TPayload>> {
2121
this.handlers[type] = handler;
2222

2323
return this;
2424
}
2525

2626
reduce(
2727
state: TState,
28-
action: HandlersToDiscriminatedUnion<THandlers>,
28+
action: PayloadsToDiscriminatedUnion<TPayloadMap>
2929
): TState {
3030
const handler = this.handlers[action.type];
3131
if (!handler) {
@@ -49,19 +49,28 @@ const reducer = new DynamicReducer<State>()
4949
username: action.username,
5050
password: action.password,
5151
};
52-
},
52+
}
5353
)
5454
.addHandler("LOG_OUT", () => {
5555
return {
5656
username: "",
5757
password: "",
5858
};
59+
})
60+
.addHandler("UPDATE_USERNAME", (state, action: { username: string }) => {
61+
return {
62+
...state,
63+
username: action.username,
64+
};
5965
});
6066

6167
it("Should return the new state after LOG_IN", () => {
6268
const state = reducer.reduce(
6369
{ username: "", password: "" },
64-
{ type: "LOG_IN", username: "foo", password: "bar" },
70+
{
71+
type: "UPDATE_USERNAME",
72+
username: "awdawdawd",
73+
}
6574
);
6675

6776
type test = [Expect<Equal<typeof state, State>>];
@@ -72,7 +81,7 @@ it("Should return the new state after LOG_IN", () => {
7281
it("Should return the new state after LOG_OUT", () => {
7382
const state = reducer.reduce(
7483
{ username: "foo", password: "bar" },
75-
{ type: "LOG_OUT" },
84+
{ type: "LOG_OUT" }
7685
);
7786

7887
type test = [Expect<Equal<typeof state, State>>];
@@ -86,7 +95,7 @@ it("Should error if you pass it an incorrect action", () => {
8695
{
8796
// @ts-expect-error
8897
type: "NOT_ALLOWED",
89-
},
98+
}
9099
);
91100
});
92101

@@ -96,6 +105,6 @@ it("Should error if you pass an incorrect payload", () => {
96105
// @ts-expect-error
97106
{
98107
type: "LOG_IN",
99-
},
108+
}
100109
);
101110
});

0 commit comments

Comments
 (0)