diff --git a/advent-of-ts/day-17.ts b/advent-of-ts/day-17.ts new file mode 100644 index 0000000..c931a92 --- /dev/null +++ b/advent-of-ts/day-17.ts @@ -0,0 +1,52 @@ +const compose = + (f: (a: A) => B, g: (b: B) => C, h: (c: C) => D) => + (a: A): D => + h(g(f(a))); + +type FirstChar = S extends `${infer First}${string}` + ? First + : never; +type FirstItem = Items extends readonly [ + infer First, + ...unknown[] +] + ? First + : never; + +const upperCase: (s: S) => Uppercase = (x) => + x.toUpperCase() as Uppercase; +const lowerCase: (s: S) => Lowercase = (x) => + x.toLowerCase() as Lowercase; +const firstChar = (x: S): FirstChar => + x[0] as FirstChar; +const firstItem = (x: T): FirstItem => + x[0] as FirstItem; +const makeTuple = (x: T): [T] => [x] as [T]; +const makeBox = (value: T): { value: T } => ({ value }); + +// const tuple = makeTuple("hello!" as const); // Type: readonly ["hello!"] +// const item = firstItem(tuple); // Should resolve to type "hello!" +// const box = makeBox(item); // Should be { value: "hello!" } + +// // Check intermediate inferred types explicitly: +// type T1_Step1 = ReturnType; // Expect readonly ["hello!"] +// type T1_Step2 = ReturnType; // Expect "hello!" +// type T1_Step3 = ReturnType; + +import type { Equal, Expect } from "npm:type-testing"; + +const t0 = compose(upperCase, makeTuple, makeBox)("hello!").value[0]; +// ^? +type t0_actual = typeof t0; // => +type t0_expected = "HELLO!"; // => +type t0_test = Expect>; + +const t1 = compose(makeTuple, firstItem, makeBox)("hello!" as const).value; +type t1_actual = typeof t1; // => +type t1_expected = "hello!"; // => +type t1_test = Expect>; + +const t2 = compose(upperCase, firstChar, lowerCase)("hello!"); +type t2_actual = typeof t2; // => +type t2_expected = "h"; // => +type t2_test = Expect>;