Share
Embed
Transcript
17 slides
-
STEP①:張り紙の曜⽇を、型で表してみよう まずは架空の簡単なルールで試してみよう type GarbageRules = { burnable: "monday" | "wednesday";
resource: | "second-wednesday" | "fourth-wednesday"; }; type CollectionDay<G extends keyof GarbageRules> = GarbageRules[G]; 許可する組み合わせだけを型にする。 -
……でも、同じルールを値と型に2回書いてない? // 値:実行時のチェック(分岐)で使う。例:読み取ったゴミを、今日出してよい か const rules = { burnable: ["monday",
"wednesday"] }; const ok = rules[scannedGarbage].includes(today); // 型:コンパイル時のチェックで使う(実行時は消える) type GarbageRules = { burnable: "monday" | "wednesday"; }; 型は実⾏時に消えるので、分岐で使う値も別に要る。 同じ「⽉‧⽔」を2回書くと、ルール変更があった場合に 更新漏れが起きる可能性有り。堅牢とは⾔えない。 -
STEP②:ルールは値に1回だけ書く。 型はそこから作る! const rules = { burnable: ["monday", "wednesday"], resource:
["second-wednesday", "fourth-wednesday"], } as const; type Rules = typeof rules; type GarbageType = keyof Rules; type CollectionDay<G extends GarbageType> = Rules[G][number]; type GarbageSchedule = { [G in GarbageType]: { garbage: G; day: CollectionDay<G> }; }[GarbageType]; as const → typeof → keyof → Indexed Access → Mapped Types -
知⼈から隣町の物件も追加で頼まれた。 ルールの書き⽅も、型で決める! type Weekday = "monday" | "tuesday" | /*
… */ "sunday"; type Nth = 1 | 2 | 3 | 4 | 5; // その月の何回目か // ルールは2種類:「曜日」か「第N曜日」 type CollectionRule = | { type: "weekday"; weekdays: readonly Weekday[] } | { type: "nth-weekday"; nth: readonly Nth[]; weekday: Weekday }; type GarbageRule = { schedules: readonly CollectionRule[]; excludeDates: readonly ISODate[]; // 年末年始など }; 「曜⽇」か「第N曜⽇」かを type で⾒分ける判別付きUnion。 紙類の「2‧4⾦」は nth: [2, 4] -
卸町と河原町のルールの記述例 // 年末年始は収集なし(日付は仮置き) const yearEnd = ["2026-12-29", /* … */
"2027-01-03"] as const; const rules = { oroshimachi: { // 卸町 household: { schedules: [{ type: "weekday", weekdays: ["monday", "thursday"] }], excludeDates: yearEnd }, paper: { schedules: [{ type: "nth-weekday", nth: [2, 4], weekday: "friday" }], excludeDates: yearEnd }, }, kawaramachi: { // 河原町 household: { schedules: [{ type: "weekday", weekdays: ["wednesday", "saturday"] }], excludeDates: yearEnd }, }, } as const; 収集曜⽇の出典: 仙台市「⽣活ごみ収集曜⽇⼀覧(若林区)」 令和7年7⽉1⽇版(抜粋) -
STEP③:⽇付も、型で判定したい! // 1日分の判定:除外日なら false、それ以外はルールで判定 type IsCollectionDate<A extends Area, G extends
GarbageType<A>, D extends KnownDate> = D extends ExcludedDate<A, G> ? false : true extends MatchesRule<ConfiguredRule<A, G>, D> ? true : false; // 31日分を回し、収集日だけを Union に残す type CollectionDate<A extends Area, G extends GarbageType<A>> = { [D in KnownDate]: IsCollectionDate<A, G, D> extends true ? D : never; }[KnownDate]; function putOut<A extends Area, G extends GarbageType<A>>( area: A, garbage: G, date: CollectionDate<A, G>) { /* … */ } MatchesRule は、 ⽇付がルール(曜⽇‧第N曜⽇)に合うかを判定(中⾝は省略) -
型の答え:卸町の家庭ごみは、この8⽇だけ type A = CollectionDate<"oroshimachi", "household">; // = "2026-12-03" |
"2026-12-07" | "2026-12-10" // | "2026-12-14" | "2026-12-17" | "2026-12-21" // | "2026-12-24" | "2026-12-28" type B = CollectionDate<"oroshimachi", "paper">; // = "2026-12-11" | "2026-12-25" putOut("oroshimachi", "paper", "2026-12-11"); // OK: 第2金曜 putOut("oroshimachi", "paper", "2026-12-18"); // Error: 第3金曜 putOut("kawaramachi", "household", "2026-12-05"); // OK: 土曜も回収 putOut("oroshimachi", "household", "2026-12-31"); // Error: 年末年始 -
ルールを変えたら、 直す場所をコンパイラが教えてくれる もし卸町の家庭ごみから⽉曜が消えたら… - weekdays: ["monday", "thursday"], + weekdays: ["thursday"],
// 卸町の家庭ごみ putOut("oroshimachi", "household", "2026-12-07"); 12/7(⽉)の記述が、コンパイルエラーになる error TS2345: Argument of type '"2026-12-07"' is not assignable to parameter of type 'CollectionDate<"oroshimachi", "household">'. -
⾃⼰紹介 • 名前:かなと • エンジニア歴:1年半 • 会社:トグルホールディングス(10/30 に上場しました) • 地元:仙台(地元開催嬉しい)
• 最近の趣味:ウクレレ(1週間前に買ったばかり) X: @kanato_typo