Skip to content

Commit ea7b8c1

Browse files
committed
add day 17
1 parent e03c527 commit ea7b8c1

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

2024/17/index.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type { Expect, Equal } from "type-testing";
2+
3+
type Compose = <A, B, C, D>(
4+
f: (x: A) => B,
5+
g: (x: B) => C,
6+
h: (x: C) => D,
7+
) => (a: A) => D;
8+
9+
const compose: Compose = (f, g, h) => (a) => h(g(f(a)));
10+
11+
type FirstChar<T extends string> = T extends `${infer F}${string}` ? F : never;
12+
13+
const upperCase = <T extends string>(x: T) => x.toUpperCase() as Uppercase<T>;
14+
const lowerCase = <T extends string>(x: T) => x.toLowerCase() as Lowercase<T>;
15+
const firstChar = <T extends string>(x: T) => x[0] as FirstChar<T>;
16+
const firstItem = <T extends unknown[]>(x: T) => x[0] as T[0];
17+
const makeTuple = <T>(x: T) => [x];
18+
const makeBox = <T>(value: T) => ({ value });
19+
20+
// ------------------- Test section ---------------------
21+
22+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
23+
const t0 = compose(upperCase, makeTuple, makeBox)("hello!").value[0]!;
24+
// ^?
25+
type t0_actual = typeof t0; // =>
26+
type t0_expected = "HELLO!"; // =>
27+
type t0_test = Expect<Equal<t0_actual, t0_expected>>;
28+
29+
const t1 = compose(makeTuple, firstItem, makeBox)("hello!" as const).value;
30+
type t1_actual = typeof t1; // =>
31+
type t1_expected = "hello!"; // =>
32+
type t1_test = Expect<Equal<t1_actual, t1_expected>>;
33+
34+
const t2 = compose(upperCase, firstChar, lowerCase)("hello!");
35+
type t2_actual = typeof t2; // =>
36+
type t2_expected = "h"; // =>
37+
type t2_test = Expect<Equal<t2_actual, t2_expected>>;

0 commit comments

Comments
 (0)