やりたいこと
例えば1 ~ 100の任意の整数値を取る型を作りたい
// イメージ type Range100 = Range<1, 100> const test: Range100 = 100; // ok const test1: Range100 = 1; // ok const test2: Range100 = 101; // ng
解決策
type-festというライブラリのIntRangeに解決策があります。実装を確認すると、StartとEndを指定してEndになるまで再帰的に処理しています。
もう少し簡潔な方法で実装している方もいらっしゃいます。
この程度であればライブラリの実装を移植すれば良さそうですが、自分で思いつくには難しい。
うまくいかないやり方
const array = []; for (let i = 1; i < 101; i++) { array.push(i); } type Range100 = typeof array[number]; const test2: Range100 = 101;
解決策のやり方が難しいと思うと、こういうわかりやすい方法にしたくなりますが、この方法はうまくいきません。arrayの内容が実行時に決まるので、コンパイル時に行われるTypeScriptの型推論が効かずRange100
はnumber型として推論されます。
同様の理由で以下もうまくいきません。
const array: number[] = Array.from({ length: 100 }, (_, i) => i + 1); type Range100 = typeof array[number]; const test1: Range100 = 101;
もちろんうまくいくやり方
type Range100 = 1 | 2 | 3 | 4 | 5 | 6 ...(略) | 100
あるいはコンパイル時に値が決まる
const range = [1,2,3,4, ...(略), 100] as const; type Range100 = typeof range[number]
も当然OKです。後者はUnion Typeを作る際によく使いますね。