Skip to content

Commit 8da1e8f

Browse files
committed
Day 23.
1 parent bc978ed commit 8da1e8f

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed

2024/day-23.ts

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { Expect, Equal } from "../test";
2+
3+
/**
4+
* **Upgrade the Assembly Line**
5+
*
6+
* The North Pole's toy assembly line is getting a major upgrade! To streamline production, the elves need to build a type-safe conveyor belt system that can standardize their operations and make them reusable. The system should introduce an `Apply` type that can be used to apply operations to values.
7+
*
8+
* The system should support the following operations:
9+
* - `Push`: Add an item to a tuple
10+
* - `Extends`: Check if a type extends another type
11+
* - `Filter`: Filter items in a tuple based on any criteria
12+
* - `ApplyAll`: Apply an operation to all items in a tuple
13+
* - `Cap`: Capitalize the first letter of a string
14+
*
15+
* Example usage of the conveyor belt system:
16+
* ```ts
17+
* type Station1 = Apply<Cap, "robot">; // "Robot"
18+
* type Station2 = Apply<Apply<Push, Station1>, ["Tablet", "teddy bear"]>; // ["Tablet", "teddy bear", "Robot"]
19+
* type Station3 = Apply<
20+
* Apply<Filter, Apply<Extends, Apply<Cap, string>>>,
21+
* Station2
22+
* >; // ["Tablet", "Robot"]
23+
* ```
24+
*
25+
* Hint
26+
*
27+
* Generic types like `Array` let you abstract over the type of the element (`T`) in the container (`Array`). But what if you need to abstract over the type of the container itself?
28+
*/
29+
type Description = any;
30+
31+
/** Apply */
32+
// prettier-ignore
33+
type Apply<Method, Param> =
34+
Method extends Cap
35+
? Capitalize<Param & string>
36+
: Method extends Push
37+
? [PushImpl, Param]
38+
: Method extends Filter
39+
? [FilterImpl, Param]
40+
: Method extends Extends
41+
? [ExtendsImpl, Param]
42+
: Method extends ApplyAll
43+
? [ApplyAllImpl, Param]
44+
: Method extends [PushImpl, infer LocalParam]
45+
? (Param extends unknown[] ? [...Param, LocalParam] : never)
46+
: Method extends [ExtendsImpl, infer ExtendType]
47+
? (Param extends ExtendType ? true : false)
48+
: Method extends [FilterImpl, infer LocalParam]
49+
? (Param extends unknown[] ? FilterFn<Param, LocalParam> : never)
50+
: Method extends [ApplyAllImpl, infer LocalParam]
51+
? (Param extends unknown[] ? ApplyAllFn<Param, LocalParam> : never)
52+
: never;
53+
54+
type FilterFn<T extends unknown[], Cond> = T extends [infer Head, ...infer Tail]
55+
? Apply<Cond, Head> extends true
56+
? [Head, ...FilterFn<Tail, Cond>]
57+
: FilterFn<Tail, Cond>
58+
: [];
59+
60+
type ApplyAllFn<T extends unknown[], Method> = T extends [infer Head, ...infer Tail]
61+
? [Apply<Method, Head>, ...ApplyAllFn<Tail, Method>]
62+
: [];
63+
64+
/** Push an element to a tuple */
65+
type Push = "Push";
66+
type PushImpl = "PushImpl";
67+
68+
/** Filter a tuple */
69+
type Filter = "Filter";
70+
type FilterImpl = "FilterImpl";
71+
72+
/** Determine if the given type extends another */
73+
type Extends = "Extends";
74+
type ExtendsImpl = "ExtendsImpl";
75+
76+
/** Apply an operation to all inputs */
77+
type ApplyAll = "ApplyAll";
78+
type ApplyAllImpl = "ApplyAllImpl";
79+
80+
/** Capitalize a string */
81+
type Cap = "Cap";
82+
83+
// *************************************************************************************
84+
// *** Tests ***
85+
// *************************************************************************************
86+
87+
type t0_actual = Apply<Cap, "hello">; // =>
88+
type t0_expected = "Hello"; // =>
89+
type t0 = Expect<Equal<t0_actual, t0_expected>>;
90+
91+
type t1_actual = Apply<
92+
// =>
93+
Apply<Push, "world">,
94+
["hello"]
95+
>;
96+
type t1_expected = ["hello", "world"]; // =>
97+
type t1 = Expect<Equal<t1_actual, t1_expected>>;
98+
99+
type t2_actual = Apply<
100+
// =>
101+
Apply<ApplyAll, Cap>,
102+
Apply<Apply<Push, "world">, ["hello"]>
103+
>;
104+
type t2_expected = ["Hello", "World"]; // =>
105+
type t2 = Expect<Equal<t2_actual, t2_expected>>;
106+
107+
type t3_actual = Apply<
108+
// =>
109+
Apply<Filter, Apply<Extends, number>>,
110+
[1, "foo", 2, 3, "bar", true]
111+
>;
112+
type t3_expected = [1, 2, 3]; // =>
113+
type t3 = Expect<Equal<t3_actual, t3_expected>>;
114+
115+
type Station1 = Apply<Cap, "robot">; // =>
116+
type Station2 = Apply<Apply<Push, Station1>, ["Tablet", "teddy bear"]>; // =>
117+
type Station3 = Apply<Apply<Filter, Apply<Extends, Apply<Cap, string>>>, Station2>;
118+
type t4_actual = Station3;
119+
type t4_expected = ["Tablet", "Robot"];
120+
type t4 = Expect<Equal<t4_actual, t4_expected>>;

0 commit comments

Comments
 (0)