2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScriptの型推論を理解するlet,var,constで変わる型の挙動

Last updated at Posted at 2025-06-24

目次

はじめに

TypeScriptは型を明示的に書かなくても、型推論(型を自動で判断)してくれる便利な機能があります。

でも「let」「const」「var」の使い方によって、推論される型が微妙に違うのをご存知ですか?

この記事では、TypeScriptの型推論変数宣言のキーワードの関係について、サンプルコードと一緒に分かりやすく解説します!


型推論とは?

まずは「型推論」って何?というところから。

たとえば、以下のように変数を定義すると

let message = "Hello, world!";
let message: string  //TypeScriptが推論した型の表示

TypeScriptは「この変数には文字列が入っているから、型は string だな」と自動で判断します。
正確には、初期化時の値を基にその変数に最も適切な型を自動で推論します。これが型推論です。

型を書かなくても、TypeScriptがいい感じに判断してくれるわけですね。
下記の場合はどうでしょうか?

const greeting = "Hello";
const greeting: "Hello"  //TypeScriptが推論した型の表示

なんと、リテラル型(文字列そのもの)になります!

これはconstで宣言された変数は再代入できないため、TypeScriptがより具体的な型(リテラル型)を推論するためです。

リテラル型とは?

「文字列」ではなく、「特定の値そのもの」を型として持つものです。

constの場合:リテラル型になる

const age = 42;

この場合、型は 42(number ではなくリテラル型)となる

リテラルを使用するメリット

・コードの可読性向上:直接的な値を示すことで、プログラムの意図が明確になります.

・デバッグの容易さ:値が直接記述されているため、どこで値が変更されたのかを特定しやすくなります.

・パフォーマンスの向上:変数に値が格納されるよりも、リテラルを使用する方が処理速度が速くなる場合があります.

letの場合:一般的な型になる

let greeting = "Hello";

こちらはどうでしょう?

let greeting: string  //TypeScriptが推論した型の表示

今度はリテラル型ではなく、一般的な string型になりました。
これは「let は後で値を変更するかもしれない」と思われるからです。

varの場合:letと同じく一般的な型

var greeting = "Hello";

推論される型は

var greeting: string  //TypeScriptが推論した型の表示

let と同じく、一般的な型になります。
ただし、var はスコープが関数単位だったり巻き上げが起きたり、重複宣言できたりとクセが強いので、最近は基本的に使われません。

比較まとめ

宣言方法 推論される型 補足
const const a = "hi" hi(リテラル型) 値の変更が不可能
let let b = "hi" string 値の変更が可能
var var c = "hi" string 値の変更が可能(※古い書き方。let推奨)
特性 var let const
初期化 ✅なくてもOK ✅ なくてもOK ❌ ないとNG
再代入 ✅ できる ✅ できる ❌ できない
再宣言(同一スコープ内) ✅ できる ❌ できない ❌ できない
スコープ 関数スコープ ブロックスコープ ブロックスコープ
巻き上げ(※Hoisting) ✅ 起きる(※undefined) ✅ 起きるが初期化前はアクセス不可 (※TDZ) ✅ 起きるが初期化前はアクセス不可 (※TDZ)

こんな時に差が出る!

たとえば、関数にリテラル型だけを受け取ってほしい場合

function greet(word: "Hello") {
  console.log(word);
}

const a = "Hello";
let b = "Hello";

greet(a); // OK
greet(b); // エラー

const の場合は "Hello" というリテラル型が推論されるので通りますが、
let の場合は string 型なのでエラーになります。

明示的に型を指定する方法

もし letvar でもリテラル型を使いたい場合は、型を明示することができます。

1.型注釈を使う方法

let greeting: "Hello" = "Hello";
var message: "hi" = "hi";

2.as constアサーションを使う方法

let greeting = "Hello" as const; // "Hello"型になる
let status = "success" as const; // "success"型になる

as constの特徴と使いどころ
as constは const assertion ( const アサーション)と呼ばれ、TypeScript 3.4で導入された機能です。

特徴

・値を最も厳密な型(リテラル型)として扱う。
・letやvarでも、constのようにリテラル型を得られる。
・型注釈よりも値から自動で型を推論してくれるため、タイプミスが起きにくい。

比較例

// 型注釈の場合:型とバリューを両方書く必要がある
let method1: "GET" = "GET";

// as const の場合:値から型が自動推論される
let method2 = "GET" as const;

// どちらも同じ "GET" 型になるが、as const の方が簡潔

注意点

ts// うっかりタイプミス
let method: "GET" = "GTE"; // エラー

// as const なら値から型が決まるので、こういうミスは起きない
let method = "GET" as const; // 必然的に "GET" 型になる

補足:型注釈によってリテラル型チェックが効かなくなる場合

TypeScriptでは、リテラル型を活かすには型注釈やアサーションの使い方に注意が必要です。

以下のようなコードでは、型注釈 anynever を使うことで、リテラル型チェックがすり抜けてしまいます。

function greet(word: 'Hello') {
  console.log(word);
}

const hello = 'Hello';            // ✅ const → リテラル型 'Hello' に推論される
let a: any = 'Hello';             // ⚠️ any型 → 型チェックが効かず通る
let b = 'Hello' as never;         // ⚠️ never型 → 絶対に呼ばれない値として扱われる

greet(hello); // ✅ OK
greet(a);     // ⚠️ 型チェックが効かない
greet(b);     // ⚠️ 実行されることは想定されていない
なぜ通るのか?

any は「すべての型との互換性を持つ」ため、関数の型注釈をバイパスしてしまいます。

never は「到達不能な値」ですが、代入時に TypeScript が特別扱いしてしまうため、一見通ってしまうように見えます。

対策

anyを使うと型の恩恵を失ってしまうため、極力避けるのがベスト。

never は主に「例外や無限ループ」の結果として使うべきで、意図的に代入するような使い方は避けるべきです。
このように、意図しない型抜けを防ぐためにも、as const と同様に 型注釈の使い方に慎重になることが重要です。

いつ使うべき?

・設定値やステータスなど、変更されない値
・Union型の判別で使う値

※ただし、多くの場合は素直にconstを使う方が自然です。as constは「letを使いたい特別な理由があるとき」の解決策として覚えておくと良いでしょう。

まとめ

・TypeScriptの型推論は、宣言方法によって挙動が変わる
・const → リテラル型(変更不可な値)
・let / var → 一般的な型(変更可能な値)
・型の厳密さが必要な場合は、const + リテラル型が強い!

参考リンク

TypeScript公式:Type Inference
TypeScript Deep Dive
サバイバルTypeScript
TypeScript公式ドキュメント(any型)
TypeScript公式ドキュメント(never型)

注釈

巻き上げ(Hoisting)
TDZ
Undefined

次回予告

今回はプリミティブ型(文字列・数値)での型推論を中心に解説しましたが、オブジェクトや配列の型推論はもう少し複雑です。
オブジェクトと配列での型推論について詳しく解説予定です。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?