no-null-in-aliases について
トップレベルの型エイリアスにnullやundefinedを含めず、使用箇所でnull許容を表すTypeScriptスキルです。型の可読性を高め、リファクタリング時にnull関連のエラーを検出しやすくします。
主な機能
- 01トップレベルの型エイリアスを非nullに保つ
- 02使用箇所でType | nullと記述
- 03必要ならnull許容の型名を明示
- 04オブジェクトプロパティのnull許容
活用シーン
- 01明確なドメイン型エイリアスの定義
- 02関数引数のnull許容性の明示
- 03nullチェックを安全にするリファクタリング
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ marius-townhouse/ effective-typescript-skills --skill no-null-in-aliasesインストール後、Claude Code で/no-null-in-aliasesを入力して読み込まれたか確認します。
詳細
型エイリアスに null や undefined を含めない
概要
型エイリアスは、何かを表すべきであり、「何か、または何もないもの」を表すべきではありません。
User を見たら、ユーザーであることを期待します。ユーザーかもしれないものではありません。型エイリアスに隠すのではなく、使用箇所で明示的に null を含めてください。
このスキルを使用する場面
- 型エイリアスを定義するとき
- null を含む型に名前を付けるとき
- 分かりにくい null 許容性を理解するとき
- 関数のパラメーターを設計するとき
絶対的なルール
Type aliases should represent valid values.
Use Type | null explicitly, not NullableType.
覚えておきましょう:
Userは常にユーザーを表すべきですUser | nullは null 許容性を明示します- 隠れた null 許容性は、読み手を混乱させます
- オブジェクトのプロパティは省略可能または null 許容にできます
検出:隠れた null 許容性
// Is user nullable? Can't tell from usage
function getComments(comments: Comment[], user: User) {
return comments.filter(c => c.userId === user?.id);
}
型が次のように定義されている場合:
type User = { id: string; name: string; } | null;
オプショナルチェーン ?. が必要になります。しかし、定義を確認しないと、読み手にはそれが分かりません。
より良い方法:明示的な null 許容性
type User = { id: string; name: string; };
// Now nullability is visible at the usage site
function getComments(comments: Comment[], user: User | null) {
return comments.filter(c => c.userId === user?.id);
}
ユーザーが必須の場合は、次のようにします:
function getComments(comments: Comment[], user: User) {
return comments.filter(c => c.userId === user.id);
}
null を含める必要がある場合
明示的な名前を使用します:
// Bad: hidden null
type User = { id: string } | null;
// Better: explicit in name
type NullableUser = { id: string } | null;
// Best: no alias, explicit at usage
type User = { id: string };
function fn(user: User | null) { ... }
ネストされた null 許容性は問題ありません
このルールは、型エイリアスの最上位に適用されます。オブジェクト内の null 許容プロパティは問題ありません:
// OK: nullable property in object
interface BirthdayMap {
[name: string]: Date | undefined;
}
// BAD: nullable at top level
type BirthdayMap = {
[name: string]: Date | undefined;
} | null;
省略可能なプロパティ
省略可能なプロパティは、null 許容のプロパティと似ています:
interface User {
id: string;
name: string;
email?: string; // OK: optional property
}
ただし、省略可能なプロパティが適切な場面については、項目 33 と 37 を参考にしてください。
これが重要な理由
コードの読みやすさ
// What does this mean?
function processUser(user: User) { ... }
// If User includes null, you'd expect:
function processUser(user: User) {
if (!user) return; // But why? Isn't user required?
}
// Explicit is clearer:
function processUser(user: User | null) {
if (!user) return; // Ah, it might be null!
}
リファクタリングの安全性
// If User includes null, this might crash:
function processUser(user: User) {
console.log(user.name); // Runtime error if null
}
// With explicit typing, TypeScript catches it:
function processUser(user: User | null) {
console.log(user.name); // Error: 'user' is possibly 'null'
}
圧力に負けないための指針
1. 「こちらのほうが簡潔です」
圧力: 「NullableUser は User | null より短いです」
回答: 使用箇所で明示することには、数文字分の価値があります。
対応: 使用箇所で Type | null を使います。
2. 「常に null 許容です」
圧力: 「API から取得するユーザーは常に null 許容です」
回答: それは API の詳細であり、ユーザー自体の性質ではありません。
対応: 型の中ではなく、API 境界で null 許容性を処理します。
危険信号 — 作業を止めて再検討する
| nullまたは| undefinedで終わる型エイリアスNullableXやMaybeXという名前の型- 必須だと思っていたパラメーターに対するオプショナルチェーン
- 型に null が含まれるかどうかが分からない
よくある正当化(すべて誤り)
| 言い訳 | 実際のところ |
|---|---|
| 「null があり得ることを記述しています」 | 隠しているだけです。明示的な | null で記述できます |
| 「繰り返しが減ります」 | 明瞭さ > 簡潔さ |
| 「API から届くデータがこうなっています」 | 境界で変換します |
クイックリファレンス
// DON'T: null in type alias
type User = { id: string } | null;
// DON'T: Maybe/Nullable prefixes
type MaybeUser = User | null;
// DO: Clean type alias
type User = { id: string };
// DO: Explicit nullability at usage
function process(user: User | null) { ... }
// OK: Nullable properties inside objects
interface Config {
timeout?: number; // optional property
data: Data | null; // nullable property
}
要点
型名は、何かを表すべきであり、それかもしれないものを表すべきではありません。
User を見たら、ユーザーであることを期待できるべきです。null 許容性が重要な使用箇所では、| null を明示的に含めてください。これによりコードが読みやすくなり、TypeScript が null 関連のバグを検出しやすくなります。
参考資料
Dan Vanderkam 著「Effective TypeScript」項目 32「型エイリアスに null や undefined を含めない」に基づいています。