---
title: "typeof演算子の使い方｜JavaScriptの型判定とTypeScriptのtypeof型・keyof型"
url: "https://www.issoh.co.jp/tech/details/3762/"
published: 2024-10-07
updated: 2026-07-06
categories: ["TypeScript"]
publisher: "株式会社一創"
---

# typeof演算子の使い方｜JavaScriptの型判定とTypeScriptのtypeof型・keyof型

typeofは同じ綴りで2つの別物を指します。JavaScriptのtypeofは**値を受け取り、その型名を文字列で返す実行時の演算子**です。一方TypeScriptのtypeofは**値から型を取り出す型レベルの演算子**で、動きも使う場所もまったく違います。この記事では、JavaScriptのtypeofによる型判定と落とし穴、TypeScriptのtypeof型・keyof型、そして両者を組み合わせる`keyof typeof`イディオムまでを、実行結果つきのコード例で整理します。

## まとめ：typeofの要点（先に結論）

- **JavaScriptのtypeof**は値を受け取り、`"string"` `"number"`など8種類の型名を文字列で返す（実行時）。
- `typeof null`は`"object"`、配列も`"object"`を返す。配列判定は`Array.isArray()`、その他の内部型は`Object.prototype.toString.call()`を使う。
- 未宣言の変数に対してもtypeofはエラーを投げないため、存在チェックに使える。
- **TypeScriptのtypeof**は型を書く位置で使い、`type T = typeof obj`のように値から型を生成する（コンパイル時）。
- **keyof**は型を受け取り、そのプロパティ名のユニオン型を作る。`keyof typeof obj`で「実行時のオブジェクトのキー集合」を型として得るのが定番。

## JavaScriptのtypeof演算子とは（値の型を文字列で返す）

JavaScriptのtypeofは、直後に置いた値の型を**小文字の文字列**で返す単項演算子です。書き方は`typeof x`と`typeof(x)`のどちらでも同じ結果になります。返り値は必ず文字列なので、`typeof x === "number"`のように等価比較で分岐に使います。

```
typeof "hello";      // "string"
typeof 42;           // "number"
typeof true;         // "boolean"
typeof undefined;    // "undefined"
typeof 10n;          // "bigint"
typeof Symbol();     // "symbol"
typeof {};           // "object"
typeof function(){}; // "function"
```

### typeofが返す8種類の型名

typeofの返り値は次の8つに限られます。プリミティブ（string/number/bigint/boolean/undefined/symbol）はそれぞれ固有の文字列を返し、関数は`"function"`、それ以外のオブジェクトはすべて`"object"`にまとめられます。

| 値の例                        | typeofの返り値  |
| -------------------------- | ----------- |
| “text”, “”                 | “string”    |
| 42, NaN, Infinity          | “number”    |
| 10n                        | “bigint”    |
| true, false                | “boolean”   |
| undefined, 未宣言の変数          | “undefined” |
| Symbol()                   | “symbol”    |
| 関数, class, アロー関数           | “function”  |
| {}, \[\], null, new Date() | “object”    |

注意点は2つ。`NaN`は「非数」という名前でも`typeof NaN`は`"number"`です。数値かどうかを厳密に見たいときは`Number.isNaN()`や`Number.isFinite()`を併用します。もう1つ、classで定義したものも実体は関数なので`"function"`を返します。

### typeof nullが”object”になる歴史的仕様

もっとも有名な落とし穴が`typeof null`です。nullは「値が無い」ことを表すプリミティブですが、typeofは`"object"`を返します。

```
typeof null;   // "object"（"null" ではない）
```

これはJavaScript最初期の実装に由来するバグで、後方互換のため修正されず仕様として残っています。nullを判定したいときはtypeofに頼らず、`value === null`と直接比較するのが確実です。「nullでもundefinedでもない」を見たいときは`value != null`（緩い等価）で両方をまとめて弾けます。

### 配列・日付はすべて”object” ─ Array.isArrayで判定する

配列・日付・正規表現・プレーンなオブジェクトは、typeofではすべて`"object"`にまとめられ区別できません。配列かどうかは専用の`Array.isArray()`を使います。

```
typeof [1, 2, 3];         // "object"（配列と分からない）
Array.isArray([1, 2, 3]); // true ← 配列判定はこちら
Array.isArray("abc");     // false
```

配列以外の内部型まで細かく見分けたいときは`Object.prototype.toString.call()`が使えます。`"[object Array]"` `"[object Date]"` `"[object RegExp]"`のように内部クラス名を返すため、typeofよりも解像度が高い判定ができます。

## typeofでJavaScriptの変数の型を判定する

実務でtypeofを使う場面の中心が、変数や引数の型チェックです。文字列・数値・真偽値・undefinedはtypeofだけで安全に判定できます。

```
function formatValue(value) {
  if (typeof value === "string") return value.trim();
  if (typeof value === "number") return value.toFixed(2);
  if (typeof value === "boolean") return value ? "ON" : "OFF";
  return String(value);
}
```

### 未宣言の変数を安全に存在チェックする

typeofには他の演算子にない特性があります。**宣言されていない変数に対してもReferenceErrorを投げず、`"undefined"`を返す**という点です。

```
// someGlobal を直接参照すると未宣言なら例外だが…
if (typeof someGlobal !== "undefined") {
  // ここは変数が存在するときだけ安全に通る
  someGlobal.init();
}
```

このため、ライブラリやグローバル変数が読み込まれているかを確かめる「存在チェック」にtypeofが使われます。`if (someGlobal)`だと未宣言時にエラーになりますが、typeof経由なら落ちません。

### typeofで見分けられないケースと使い分け

**typeofで足りるのはプリミティブの大分類まで**で、オブジェクトの中身の型までは判定できません。用途で道具を切り替えてください。

| 判定したいもの              | 使う手段                             |
| -------------------- | -------------------------------- |
| 文字列・数値・真偽値・undefined | typeof                           |
| 配列かどうか               | Array.isArray()                  |
| null かどうか            | value === null                   |
| 特定クラスのインスタンス         | instanceof                       |
| Date/RegExp などの内部型   | Object.prototype.toString.call() |

```
typeof new Date();          // "object"（Dateと分からない）
new Date() instanceof Date; // true ← クラス判定は instanceof
```

とくに**外部APIのレスポンスのように「形が保証されない実行時のデータ」をtypeofで一つずつ確かめるのは避けるべき**です。プロパティごとにtypeofを並べる検証は抜け漏れやすく、ネストした構造には対応しきれません。この用途にはスキーマ検証ライブラリが向いており、TypeScriptの型と実行時チェックを同時に得られます。導入手順は[Zodの使い方入門｜TypeScript型安全バリデーション](https://www.issoh.co.jp/tech/details/7391/)にまとめています。

## TypeScriptのtypeof型（値から型を取り出す）

ここからは同じ綴りでも意味が変わります。TypeScriptでは、型を書く位置（型注釈やtypeエイリアスの右辺）にtypeofを置くと、**その値の型を取り出して再利用**できます。実行時には一切動かず、コンパイル時に型として展開されます。

```
const config = {
  host: "localhost",
  port: 8080,
};

// 値 config から型を取り出す（型位置の typeof）
type Config = typeof config;
// type Config = { host: string; port: number }
```

すでにある値を「正」として型を導出できるため、値と型を二重に手書きして食い違わせる事故を防げます。設定オブジェクトや定数テーブルの型を、定義そのものから同期させたいときに使います。

### JavaScriptのtypeofとTypeScriptのtypeofの違い

混乱の元はこの2つが同じキーワードなのに正反対だという点です。区別のコツは**「typeofがどこに書かれているか」**です。式の中（値の位置）にあれば実行時のJavaScript、型注釈の中（値を期待していない位置）にあればTypeScriptの型演算子です。

| 観点     | JavaScriptのtypeof | TypeScriptのtypeof |
| ------ | ----------------- | ----------------- |
| 受け取るもの | 値                 | 値（を型に変換）          |
| 返すもの   | 型名の文字列            | 型                 |
| いつ動くか  | 実行時               | コンパイル時のみ          |
| 書く場所   | 式の中               | 型注釈・typeの右辺       |

```
const x = 10;

const a = typeof x;   // 値 "number"（実行時のJS）
type B = typeof x;    // 型 number（コンパイル時のTS）
```

### as constと組み合わせてリテラル型を得る

TypeScriptのtypeofは`as const`と組み合わせると、幅の広い`string`ではなく具体的な文字列リテラル型が得られます。`as const`で値をリテラルとして固定し、その型をtypeofで取り出す流れです。

```
const theme = {
  primary: "#3366ff",
  radius: 8,
} as const;

type Theme = typeof theme;
// { readonly primary: "#3366ff"; readonly radius: 8 }
```

`as const`を付けない場合、`primary`は`string`、`radius`は`number`まで広がってしまいます。定数の値そのものを型として使いたいときは`as const`とtypeofをセットで使います。

## keyof演算子でオブジェクト型のキーをユニオン型にする

keyofはTypeScript専用の型演算子で、**オブジェクト型を受け取り、そのプロパティ名を文字列リテラルのユニオン型にして返します**。「この型が持つキーのどれか」を表す型を作れます。

```
type User = { id: number; name: string; email: string };

type UserKey = keyof User;
// "id" | "name" | "email"
```

### keyof typeofイディオム（値からキーの型を得る）

keyofは型を受け取るため、手元にあるのが「型」ではなく「値（オブジェクト）」のときは、先にtypeofで型へ変換してからkeyofを適用します。この`keyof typeof`の2段重ねが、実務でもっとも使うイディオムです。

```
const statusLabels = {
  active: "有効",
  inactive: "無効",
  pending: "保留",
};

// 値 → typeof で型 → keyof でキー集合
type StatusKey = keyof typeof statusLabels;
// "active" | "inactive" | "pending"
```

読み解く順番は内側からです。`typeof statusLabels`でオブジェクトの型を取り出し、その型に`keyof`を掛けてキーのユニオン型を得ています。定数テーブルのキーを型として使い回したいときの定番で、キーを増やせば型も自動で追随します。

### 型安全なプロパティアクセス関数を書く

keyofの典型的な使いどころが、ジェネリクスと組み合わせた型安全なプロパティ取得です。キーの型を`K extends keyof T`で縛ることで、存在しないキーを渡すとコンパイルエラーになります。

```
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const user = { id: 1, name: "Sato" };

getProperty(user, "name"); // string 型で返る
getProperty(user, "age");  // エラー: "age" は keyof user にない
```

返り値の型`T[K]`（インデックスアクセス型）により、`name`を渡せば`string`、`id`を渡せば`number`と、キーに応じた正確な型が返ります。文字列を直接受け取る素朴な実装ではこの安全性は得られません。

## よくある質問

### typeof nullが”object”になるのはなぜですか？

JavaScript最初期の実装に由来する歴史的なバグで、後方互換性のために修正されず仕様として残っているためです。nullを判定するときはtypeofを使わず、`value === null`と直接比較してください。

### 配列かどうかをtypeofで判定できますか？

できません。`typeof [1,2,3]`は`"object"`を返し、通常のオブジェクトと区別できません。配列判定には`Array.isArray()`を使ってください。より細かい内部型は`Object.prototype.toString.call()`で見分けられます。

### JavaScriptのtypeofとTypeScriptのtypeofは同じものですか？

綴りは同じですが別物です。式の中で使うtypeofは実行時のJavaScriptで、値の型名を文字列で返します。型注釈やtypeの右辺で使うtypeofはTypeScriptの型演算子で、値から型を取り出します。書かれている場所で見分けてください。

### keyof typeofはどんなときに使いますか？

実行時のオブジェクト（定数テーブルや設定オブジェクト）のキー集合を、型として使いたいときに使います。`typeof`で値を型に変換し、`keyof`でそのキーのユニオン型を得ます。キーを追加すれば型も自動で更新されます。

### C#やJavaのtypeofとは違うのですか？

別物です。この記事で扱うのはJavaScript／TypeScriptのtypeofで、JavaScriptでは型名の文字列を返し、TypeScriptでは型を取り出します。C#やJavaのtypeof（型情報・クラスオブジェクトの取得）とは動作も用途も異なります。言語を取り違えないよう注意してください。

## 関連記事

- [Zodの使い方入門｜npm・yarn・pnpmでのインストールとTypeScript型安全バリデーション](https://www.issoh.co.jp/tech/details/7391/)
- [Zodなど他ライブラリとの比較から見るValibotの優位性](https://www.issoh.co.jp/tech/details/7584/)
- [No-Semiスタイルのメリットとデメリットを徹底解説](https://www.issoh.co.jp/tech/details/5572/)

---

出典: [typeof演算子の使い方｜JavaScriptの型判定とTypeScriptのtypeof型・keyof型](<https://www.issoh.co.jp/tech/details/3762/>)（株式会社一創）
