diff --git a/advent-of-ts/day-10.ts b/advent-of-ts/day-10.ts new file mode 100644 index 0000000..0e811a2 --- /dev/null +++ b/advent-of-ts/day-10.ts @@ -0,0 +1,31 @@ +enum Gift { + Coal, + Train, + Bicycle, + Traditional, + SuccessorToTheNintendoSwitch, + FakeTwo, + FakeSix, + FakeSev, + TikTokPremium, + FakeNone, + Ften, + Fele, + Ftwe, + Fthreeteen, + Ffourteen, + Ffiveten, + Vape, + Fseventen, + Feight, + Fnineten, + Ftwen, + Ftwenone, + FTwentwo, + Ftwenthree, + FtwenFour, + FtwenFive, + OnTheMove, + FMaybe, + OnTheCouch, +} diff --git a/advent-of-ts/day-11.ts b/advent-of-ts/day-11.ts new file mode 100644 index 0000000..3c0c605 --- /dev/null +++ b/advent-of-ts/day-11.ts @@ -0,0 +1,5 @@ +type Excuse> = { + new (foo: Record): keyof T extends string + ? `${keyof T}: ${T[keyof T]}` + : never; +}; diff --git a/advent-of-ts/day-12.ts b/advent-of-ts/day-12.ts new file mode 100644 index 0000000..2f75811 --- /dev/null +++ b/advent-of-ts/day-12.ts @@ -0,0 +1,17 @@ +type NaughtyOrNice = T extends "Yanni" | "Petra" | "Aagya" + ? true + : false; + +type ToNumber = T extends `${infer N extends number}` + ? N + : never; + +type GetName = { + name: T[0]; + count: ToNumber; + rating: NaughtyOrNice extends true ? "nice" : "naughty"; +}; + +type FormatNames = { + [K in keyof Names]: GetName; +} & { length: Names["length"] }; diff --git a/advent-of-ts/day-13.ts b/advent-of-ts/day-13.ts new file mode 100644 index 0000000..b1e6ea1 --- /dev/null +++ b/advent-of-ts/day-13.ts @@ -0,0 +1,3 @@ +type Demand = { + demand: T; +}; diff --git a/advent-of-ts/day-14.ts b/advent-of-ts/day-14.ts new file mode 100644 index 0000000..a81c134 --- /dev/null +++ b/advent-of-ts/day-14.ts @@ -0,0 +1,3 @@ +type PerfReview = T extends AsyncGenerator + ? Thing + : never; diff --git a/advent-of-ts/day-15.ts b/advent-of-ts/day-15.ts new file mode 100644 index 0000000..bf7c1f7 --- /dev/null +++ b/advent-of-ts/day-15.ts @@ -0,0 +1,107 @@ +import type { Expect, Equal } from "npm:type-testing"; + +type GetHyphens< + T extends string, + Res extends 0[] = [] +> = T extends `-${infer Rest}` + ? GetHyphens + : [T, Res["length"]]; + +type GetRoute< + T extends string, + CurrentWord extends string = "", + Res extends [string, number][] = [], + HyphenCount extends number = 0 +> = T extends `${infer First}${infer Rest}` + ? First extends "-" + ? CurrentWord extends "" + ? GetRoute + : GetHyphens extends [infer Remaining, infer Count] + ? GetRoute< + Remaining & string, + "", + [...Res, [CurrentWord, HyphenCount]], + Count & number + > + : never + : GetRoute + : CurrentWord extends "" + ? Res + : [...Res, [CurrentWord, HyphenCount]]; + +type t0_actual = + GetRoute<"north_pole--candycane_forest----gumdrop_sea-------hawaii">; // => +type t0_expected = [ + // => + ["north_pole", 0], + ["candycane_forest", 2], + ["gumdrop_sea", 4], + ["hawaii", 7] +]; +type t0 = Expect>; + +type t1_actual = GetRoute<"a-b-c-d">; // => +type t1_expected = [ + // => + ["a", 0], + ["b", 1], + ["c", 1], + ["d", 1] +]; +type t1 = Expect>; + +type t2_actual = GetRoute<"🎅--🎄---🏠----🤶">; // => +type t2_expected = [ + // => + ["🎅", 0], + ["🎄", 2], + ["🏠", 3], + ["🤶", 4] +]; +type t2 = Expect>; + +type t3_actual = GetRoute<"">; // => +type t3_expected = []; // => +type t3 = Expect>; + +type t4_actual = GetRoute<"north_pole">; // => +type t4_expected = [["north_pole", 0]]; // => +type t4 = Expect>; + +type t5_actual = GetRoute<"a--b----c-d---e">; // => +type t5_expected = [ + // => + ["a", 0], + ["b", 2], + ["c", 4], + ["d", 1], + ["e", 3] +]; +type t5 = Expect>; + +type t6_actual = GetRoute<"--a-b">; // => +type t6_expected = [["a", 0], ["b", 1]]; // => +type t6 = Expect>; + +type t7_actual = GetRoute<"a-b--">; // => +type t7_expected = [["a", 0], ["b", 1]]; // => +type t7 = Expect>; + +type t8_actual = GetRoute<"north pole-candy.cane">; // => +type t8_expected = [["north pole", 0], ["candy.cane", 1]]; // => +type t8 = Expect>; + +type t9_actual = + GetRoute<"a--------------------------------------------------b">; // => +type t9_expected = [["a", 0], ["b", 50]]; // => +type t9 = Expect>; + +type t10_actual = GetRoute<"a--a-a---a">; // => +type t10_expected = [["a", 0], ["a", 2], ["a", 1], ["a", 3]]; // => +type t10 = Expect>; + +// @ts-expect-error should not be a generic array +type e0 = Expect>>; + +// @ts-expect-error should only accept string input +type e1 = GetRoute<123>; diff --git a/advent-of-ts/day-16.ts b/advent-of-ts/day-16.ts new file mode 100644 index 0000000..d236249 --- /dev/null +++ b/advent-of-ts/day-16.ts @@ -0,0 +1,62 @@ +type Curried

= ( + ...args: T +) => T extends [] + ? Curried + : T["length"] extends 0 + ? Curried + : T extends PartialTuple

+ ? Drop extends [] + ? R + : Curried, R> + : never; + +type PartialTuple

= P extends [infer First, ...infer Rest] + ? [] | [First] | [First, ...PartialTuple] + : []; + +type Drop< + T extends any[], + N extends number, + I extends any[] = [] +> = I["length"] extends N + ? T + : T extends [any, ...infer Rest] + ? Drop + : []; + +type Curry any> = F extends ( + ...args: infer P +) => infer R + ? Curried + : never; + +declare function DynamicParamsCurrying any>( + f: F +): Curry; + +const originalCurry = ( + ingredient1: number, + ingredient2: string, + ingredient3: boolean, + ingredient4: Date +) => true; + +const spikedCurry = DynamicParamsCurrying(originalCurry); + +// Direct call +const t0 = spikedCurry(0, "Ziltoid", true, new Date()); + +// Partially applied +const t1 = spikedCurry(1)("The", false, new Date()); + +// Another partial +const t2 = spikedCurry(0, "Omniscient", true)(new Date()); + +// You can keep callin' until the cows come home: it'll wait for the last argument +const t3 = spikedCurry()()()()(0, "Captain", true)()()()(new Date()); + +// currying is ok +const t4 = spikedCurry("Spectacular", 0, true); + +// @ts-expect-error arguments provided in the wrong order +const e0 = spikedCurry("Nebulo9", 0, true)(new Date()); diff --git a/advent-of-ts/day-9.ts b/advent-of-ts/day-9.ts new file mode 100644 index 0000000..0b40cb8 --- /dev/null +++ b/advent-of-ts/day-9.ts @@ -0,0 +1,9 @@ +// @ts-expect-error module intended +declare module "santas-special-list" { + type Status = "naughty" | "nice"; + type Child = { + name: string; + status: Status; + }; + type List = Child[]; +} diff --git a/deno.lock b/deno.lock index 9c98ef6..ea42ea1 100644 --- a/deno.lock +++ b/deno.lock @@ -1,7 +1,8 @@ { "version": "4", "specifiers": { - "npm:@types/node@*": "22.5.4" + "npm:@types/node@*": "22.5.4", + "npm:type-testing@*": "0.2.0" }, "npm": { "@types/node@22.5.4": { @@ -10,6 +11,9 @@ "undici-types" ] }, + "type-testing@0.2.0": { + "integrity": "sha512-HAf4o9LjUAh9xEIXZTNm+ak2tjTgK64QhTlT/D8UNedII2/eagdEbtbaVK6920K7+QBrwfvxpjPGlfWVKZ+MZQ==" + }, "undici-types@6.19.8": { "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" } diff --git a/main.ts b/main.ts index 81ab89b..b3158da 100644 --- a/main.ts +++ b/main.ts @@ -1 +1,5 @@ // hi +const test = `0123 +1234 +8765 +9876`;