- Day 3:型推論と「ちょっとクセのある型」を知る
- 型推論:TypeScriptが「いい感じに推測してくれる」
- any:なんでも入ってしまう「危険な自由」
- unknown:よく分からないけれど、慎重に扱う型
- void:何も返さない関数のための型
- never:絶対に戻ってこない関数の型
- null と undefined:値が「ない」ことを表す型
- 実践:型推論を確認しつつ、特殊な型に触れてみる
- Day 3のまとめ
- Day 3:型推論と「クセのある型」をじっくり触る
- 型推論のおさらいから始める
- any:なんでも入る「危険な自由」
- unknown:慎重な「よく分からない型」
- any と unknown の違いをコードで確認する
- undefined を扱う:まだ値が決まっていない状態
- null を扱う:意図的に「値がない」とする
- 実践テンプレート:any / unknown / null / undefined をまとめて触る
- Day 3のまとめ
Day 3:型推論と「ちょっとクセのある型」を知る
Day 3では、TypeScriptの“頭の良さ”である 型推論 と、少しクセのある特殊な型たち——any, unknown, void, never, null, undefined——を、雑誌の特集記事を読むような感覚でじっくり見ていきます。 今日は「型推論を確認する」という実践を通して、TypeScriptがどこまで自動で助けてくれるのか、そしてどこからは自分で意識して型を選ぶべきなのかを体感していきます。
型推論:TypeScriptが「いい感じに推測してくれる」
まずは、今日の主役である 型推論 から始めます。
型推論とは何か
型推論とは、「変数や式に対して、TypeScriptが自動的に型を決めてくれる仕組み」です。
// 型を書いていないけれど…
let name = "Alice"; // TypeScript は「これは string だな」と推論する
let age = 25; // 「これは number だな」と推論する
let isStudent = true; // 「これは boolean だな」と推論する
TypeScriptここでは : string や : number と書いていませんが、TypeScriptは代入された値を見て「これは文字列」「これは数値」と判断してくれます。
型推論のメリット
- すべてに型注釈を書かなくても、ある程度安全にコードを書ける
- コードが短く、読みやすくなる
- それでも「間違った型を入れようとするとエラーになる」という安心感は保たれる
let age = 25; // number と推論される
// age = "25"; // エラー: Type 'string' is not assignable to type 'number'.
TypeScript「TypeScriptは、必要なところではちゃんと守ってくれるけれど、全部を手取り足取り書かなくてもいい」というバランス感覚が、型推論の魅力です。
実践:型推論を確認してみる
型推論を確認する簡単なコードを書いてみます。
// inference-check.ts
// 型推論を確認するためのコード
let name = "Alice"; // 推論: string
let age = 25; // 推論: number
let isStudent = true; // 推論: boolean
// 途中で別の型を入れようとしてみる
// 下の行のコメントを外すと、コンパイルエラーになります
// name = 123; // エラー: number を string に代入しようとしている
// age = "25"; // エラー: string を number に代入しようとしている
// isStudent = "yes"; // エラー: string を boolean に代入しようとしている
console.log("名前:", name);
console.log("年齢:", age);
console.log("学生ですか?", isStudent);
TypeScriptこのように、型を書いていなくても、TypeScriptは「最初に入れた値」を基準に型を決めてくれます。 その後は、その型に合わない値を入れようとすると、ちゃんと止めてくれるわけです。
any:なんでも入ってしまう「危険な自由」
次に、特殊な型の代表格である any を見ていきます。
any とは
any は、「どんな型でも入ってしまう、完全に自由な型」です。
// any の例
let value: any = "Hello";
console.log(value);
value = 123;
console.log(value);
value = true;
console.log(value);
TypeScriptany にすると、文字列でも数値でも真偽値でも、何でも代入できます。 一見すると便利そうですが、TypeScriptの「型による安全性」がほぼ失われてしまいます。
any の問題点
- 間違った型を入れても、コンパイル時にエラーにならない
- 「何が入るのか」が分からないので、コードの意図が読みづらくなる
- 大規模なコードになるほど、バグの温床になりやすい
let value: any = "Hello";
value.toUpperCase(); // これは動く
value = 123;
// ここで実行時にエラーになる可能性がある
// value.toUpperCase(); // number には toUpperCase がない
TypeScript結論として、any は「どうしても必要なときだけ使うべき、最後の手段」だと考えておくと安全です。
unknown:よく分からないけれど、慎重に扱う型
unknown は、any に似ていますが、「安全寄りの“よく分からない型”」です。
unknown とは
unknown は、「何が入るか分からないけれど、使うときにはちゃんとチェックしてね」という型です。
// unknown の例
let value: unknown;
value = "Hello";
value = 123;
value = true;
// 直接は使えない
// console.log(value.toUpperCase()); // エラー: Object is of type 'unknown'.
TypeScriptunknown 型の値は、そのままではほとんど何もできません。 「使う前に、ちゃんと型を確認してね」というルールが強制されるのがポイントです。
unknown を安全に使う
let value: unknown = "Hello";
if (typeof value === "string") {
// ここに来た時点で value は string だと分かる
console.log(value.toUpperCase());
} else {
console.log("文字列ではありません");
}
TypeScriptポイント:
unknownは、「何が来るか分からない外部入力」などに向いています。anyよりも安全で、「ちゃんとチェックする習慣」を身につけるのに役立ちます。
void:何も返さない関数のための型
次は、関数でよく出てくる void です。
void とは
void は、「何も値を返さない関数の戻り値の型」として使われます。
// void の例
function greet(name: string): void {
console.log(`Hello, ${name}`);
// return しない(何も返さない)
}
greet("Alice");
TypeScriptポイント:
voidは「戻り値がない」ということを表します。- 「この関数は何かを返すのではなく、何かを“する”だけ」という意図が伝わります。
never:絶対に戻ってこない関数の型
少しマニアックですが、TypeScriptらしい型として never があります。
never とは
never は、「絶対に値を返さない(正常に終わらない)関数の戻り値の型」です。
// never の例
function throwError(message: string): never {
throw new Error(message); // ここで例外を投げて、関数は戻ってこない
}
function infiniteLoop(): never {
while (true) {
// 永遠にループする
}
}
TypeScriptポイント:
neverは、「この関数は正常に終わることがない」ということを型で表現します。- 実務ではそこまで頻繁には使いませんが、TypeScriptの型システムの奥深さを感じられる型です。
null と undefined:値が「ない」ことを表す型
最後に、null と undefined を整理します。
null とは
null は、「意図的に値が存在しないことを表す値」です。
let middleName: string | null = null; // ミドルネームがない場合
console.log(middleName); // null
TypeScriptポイント:
- 「ここには値が入る可能性があるけれど、今は“ない”」という状態を表現します。
- 型としては
string | nullのように、他の型と組み合わせて使うことが多いです。
undefined とは
undefined は、「まだ値が設定されていない状態」を表す値です。
let nickname: string | undefined;
console.log(nickname); // undefined(まだ何も代入していない)
TypeScriptポイント:
- 「変数はあるけれど、まだ値が決まっていない」という状態を表します。
- こちらも
string | undefinedのように、他の型と組み合わせて使われます。
実践:型推論を確認しつつ、特殊な型に触れてみる
最後に、今日の内容をまとめた「実践用テンプレート」を用意します。 型推論を確認しながら、any, unknown, void, never, null, undefined に軽く触れてみるコードです。
// day3-practice.ts
// Day 3 練習:型推論と特殊な型を確認する
// 1. 型推論の確認
let name = "Alice"; // 推論: string
let age = 25; // 推論: number
let isStudent = true; // 推論: boolean
console.log("=== 型推論の確認 ===");
console.log("名前:", name);
console.log("年齢:", age);
console.log("学生ですか?", isStudent);
// 間違った型を入れてみる(コメントを外すとエラーになります)
// name = 123; // エラー
// age = "25"; // エラー
// isStudent = "yes"; // エラー
// 2. any の例(危険な自由)
let anything: any = "Hello";
anything = 123;
anything = true;
console.log("=== any の例 ===");
console.log("anything の値:", anything);
// 3. unknown の例(慎重な「よく分からない」)
let something: unknown = "Hello";
console.log("=== unknown の例 ===");
if (typeof something === "string") {
// 型チェックをした上で使う
console.log("文字列として扱います:", something.toUpperCase());
} else {
console.log("文字列ではありません");
}
// 4. void の例(何も返さない関数)
function logProfile(name: string, age: number): void {
console.log(`プロフィール: 名前=${name}, 年齢=${age}`);
}
console.log("=== void の例 ===");
logProfile(name, age);
// 5. never の例(実際に呼ぶと危険なので、定義だけ)
function throwError(message: string): never {
throw new Error(message);
}
// 6. null / undefined の例
let middleName: string | null = null;
let nickname: string | undefined;
console.log("=== null / undefined の例 ===");
console.log("ミドルネーム:", middleName); // null
console.log("ニックネーム:", nickname); // undefined
TypeScriptこのコードを少しずつ動かしながら、「どこで型推論が効いているか」「どこでエラーが出るか」「どの型がどんな意味を持っているか」を、ゆっくり確認してみてください。
Day 3のまとめ
Day 3では、次のポイントを押さえました。
- 型推論:TypeScriptが自動で型を決めてくれる仕組み
any:何でも入ってしまうが、型安全性を失う「危険な自由」unknown:何が入るか分からないが、使う前にチェックを求める「慎重な型」void:何も値を返さない関数の戻り値の型never:絶対に戻ってこない関数の戻り値の型null/undefined:値が「ない」ことを表す型
ここまで来ると、TypeScriptの「型の世界」がだいぶ立体的に見えてきたはずです。 次のDayでは、配列やオブジェクトといった「複数の値をまとめて扱う型」に進んでいきます。 今日のコードは、ぜひ何度か書き直して、「TypeScriptがどこまで守ってくれているのか」を自分の目で確かめてみてください。
Day 3:型推論と「クセのある型」をじっくり触る
Day 3では、TypeScriptの中でも少しクセのある型——any, unknown, null, undefined——を中心に、型推論と合わせてじっくり見ていきます。 今日は「実際にコードを書いて、わざと危なそうなところも触ってみる」ことで、TypeScriptがどこまで守ってくれるのか、そしてどこからは自分で気をつけるべきなのかを体感していく流れです。
型推論のおさらいから始める
まずは、土台になる 型推論 を軽くおさらいしておきます。
型推論とは
型推論とは、「変数や式に対して、TypeScriptが自動的に型を決めてくれる仕組み」です。
// 型を書いていないけれど…
let name = "Alice"; // TypeScript は「これは string だな」と推論する
let age = 25; // 「これは number だな」と推論する
let isStudent = true; // 「これは boolean だな」と推論する
console.log("名前:", name);
console.log("年齢:", age);
console.log("学生ですか?", isStudent);
TypeScriptここでは : string や : number と書いていませんが、TypeScriptは代入された値を見て「これは文字列」「これは数値」と判断してくれます。
型推論の安心ポイント
let age = 25; // number と推論される
// age = "25"; // エラー: Type 'string' is not assignable to type 'number'.
TypeScript- 型を書いていなくても、「最初に入れた値」から型が決まる
- その後は、その型に合わない値を入れようとすると、コンパイル時にエラーになります
この「自動で決めてくれるけれど、ちゃんと守ってくれる」というバランスが、TypeScriptの心強いところです。
any:なんでも入る「危険な自由」
ここから、今日の主役のひとつ any に入っていきます。
any とは何か
any は、「どんな型でも入ってしまう、完全に自由な型」です。
// any を使ったコードの例
let value: any = "Hello"; // 最初は文字列
console.log("value:", value);
value = 123; // 数値を代入
console.log("value:", value);
value = true; // 真偽値を代入
console.log("value:", value);
TypeScriptポイント:
anyにすると、文字列・数値・真偽値など、何でも代入できます。- 一見便利そうですが、TypeScriptの「型による安全性」がほぼ失われてしまいます。
any の危険さを体験してみる
// any の危険な例
let anything: any = "Hello";
// 文字列としては問題ない
console.log(anything.toUpperCase());
anything = 123;
// ここで実行時に問題が起きる可能性がある
// コンパイルは通るが、実行するとエラーになることがあります
// console.log(anything.toUpperCase()); // number には toUpperCase がない
TypeScript重要なポイント:
anyは「コンパイル時には何も言わない」ので、間違いに気づくのが遅くなります。- 小さなスクリプトならまだしも、コードが大きくなるとバグの温床になりやすいです。
結論として、any は「どうしても必要なときだけ使う最後の手段」として扱うのが安全です。
unknown:慎重な「よく分からない型」
次に、any に似ているけれど、ずっと安全寄りな unknown を見ていきます。
unknown とは何か
unknown は、「何が入るか分からないけれど、使うときにはちゃんとチェックしてね」という型です。
// unknown を使ったコードの例
let value: unknown;
value = "Hello";
value = 123;
value = true;
// 直接は使えない
// console.log(value.toUpperCase()); // エラー: Object is of type 'unknown'.
TypeScriptポイント:
unknownも「何でも入る」点ではanyに似ています。- ただし、そのままではほとんど何もできないという制限があります。
- 「使う前に型を確認する」ことを強制してくれるのが、
unknownの良さです。
unknown を安全に使う練習
// unknown を安全に扱う例
let input: unknown = "Hello TypeScript";
if (typeof input === "string") {
// ここに来た時点で input は string だと分かる
console.log("文字列として扱います:", input.toUpperCase());
} else {
console.log("文字列ではありません");
}
TypeScriptここが大事:
unknownは、「外部から来るデータ」や「何が入るか分からない入力」に向いています。anyと違って、「ちゃんとチェックしてから使う」という習慣を身につけるのに役立ちます。
any と unknown の違いをコードで確認する
ここで、any と unknown の違いを、並べて見てみます。
// any と unknown の違いを確認するコード
let anyValue: any = "Hello";
let unknownValue: unknown = "Hello";
console.log("=== any の場合 ===");
console.log(anyValue.toUpperCase()); // コンパイルも実行も通る
console.log("=== unknown の場合 ===");
// console.log(unknownValue.toUpperCase()); // コンパイルエラーになる
// unknown は型チェックをすれば使える
if (typeof unknownValue === "string") {
console.log(unknownValue.toUpperCase());
}
TypeScript違いのまとめ:
any:- 何でもできる
- コンパイル時に止めてくれない
- 実行時にエラーになる可能性が高い
unknown:- 何でも入るが、そのままではほとんど何もできない
- 使う前に型チェックが必要
- 結果として、安全性が高い
「自由すぎて危ないのが any、慎重で安全寄りなのが unknown」というイメージを持っておくと、選びやすくなります。
undefined を扱う:まだ値が決まっていない状態
次は、undefined を扱ってみます。
undefined とは
undefined は、「まだ値が設定されていない状態」を表す値です。
// undefined を扱う例
let nickname: string | undefined;
console.log("ニックネーム:", nickname); // まだ何も代入していないので undefined
nickname = "Ali";
console.log("ニックネーム(設定後):", nickname);
TypeScriptポイント:
- 「変数はあるけれど、まだ値が決まっていない」という状態を表現できます。
- 型としては
string | undefinedのように、他の型と組み合わせて使うことが多いです。
undefined をチェックする
let nickname: string | undefined;
if (nickname === undefined) {
console.log("ニックネームはまだ設定されていません");
} else {
console.log("ニックネーム:", nickname);
}
TypeScript「値があるかどうか」を意識してコードを書く習慣は、バグを減らすうえでとても大事です。
null を扱う:意図的に「値がない」とする
続いて、null を扱ってみます。
null とは
null は、「意図的に値が存在しないことを表す値」です。
// null を扱う例
let middleName: string | null = null; // ミドルネームがない場合
console.log("ミドルネーム:", middleName); // null
TypeScriptポイント:
- 「ここには値が入る可能性があるけれど、今は“ない”」という状態を表現します。
string | nullのように、他の型と組み合わせて使うのが一般的です。
null をチェックする
let middleName: string | null = null;
if (middleName === null) {
console.log("ミドルネームはありません");
} else {
console.log("ミドルネーム:", middleName);
}
TypeScriptundefined と null は似ていますが、
undefined:まだ設定されていないnull:意図的に「ない」としている
というニュアンスの違いがあります。
実践テンプレート:any / unknown / null / undefined をまとめて触る
最後に、今日の練習テーマをすべてまとめたコードテンプレートを用意します。 このままコピーして、少しずつ書き換えながら「感覚」をつかんでいくのがおすすめです。
// day3-practice.ts
// Day 3 練習:any / unknown / null / undefined をまとめて確認する
console.log("=== any を使ったコード ===");
let anyValue: any = "Hello";
console.log("anyValue:", anyValue);
// どんな型でも代入できる
anyValue = 123;
console.log("anyValue:", anyValue);
anyValue = true;
console.log("anyValue:", anyValue);
// 危険な例(コンパイルは通るが、実行時に問題になる可能性)
// anyValue = 123;
// console.log(anyValue.toUpperCase()); // 実行時エラーの可能性
console.log("=== unknown を使ったコード ===");
let unknownValue: unknown = "Hello TypeScript";
// 直接は使えない(コメントを外すとコンパイルエラー)
// console.log(unknownValue.toUpperCase());
if (typeof unknownValue === "string") {
console.log("文字列として扱います:", unknownValue.toUpperCase());
} else {
console.log("文字列ではありません");
}
console.log("=== any と unknown の違いを確認 ===");
let anyExample: any = "Hello";
let unknownExample: unknown = "Hello";
console.log("any の場合はそのまま使える:", anyExample.toUpperCase());
// unknown の場合は型チェックが必要
if (typeof unknownExample === "string") {
console.log("unknown でも型チェックすれば使える:", unknownExample.toUpperCase());
}
console.log("=== undefined を扱う ===");
let nickname: string | undefined;
console.log("ニックネーム(未設定):", nickname); // undefined
nickname = "Ali";
if (nickname === undefined) {
console.log("ニックネームはまだ設定されていません");
} else {
console.log("ニックネーム(設定後):", nickname);
}
console.log("=== null を扱う ===");
let middleName: string | null = null;
if (middleName === null) {
console.log("ミドルネームはありません");
} else {
console.log("ミドルネーム:", middleName);
}
TypeScriptこのコードを少しずつ動かしながら、
anyはどこまで自由で、どこが危ないのかunknownはどうやって安全に使うのかnullとundefinedは、どんな場面で使い分けるのか
を、自分の目と手で確かめてみてください。
Day 3のまとめ
Day 3では、次のポイントを押さえました。
- 型推論:TypeScriptが自動で型を決めてくれる仕組み
any:何でも入るが、型安全性を失う「危険な自由」unknown:何でも入るが、使う前にチェックを求める「慎重な型」undefined:まだ値が設定されていない状態null:意図的に「値がない」とする状態anyとunknownの違いを、実際のコードで確認することの大切さ
ここまで来ると、TypeScriptの「型の世界」がかなり立体的に見えてきているはずです。 次のDayでは、配列やオブジェクトといった「複数の値をまとめて扱う型」に進んでいきます。 今日のコードは、ぜひ何度か書き直して、「TypeScriptがどこまで守ってくれているのか」「どこからは自分の判断が必要なのか」を、じわっと体に染み込ませていってください。
