解決方法:プライベート識別子があるためプロパティにアクセスできません (TS18013)

intermediate🔵 TypeScript2026-07-13| TypeScript 3.8+, Node.js, Modern Browsers (ES2020+)

Error Message

Property '#field' is not accessible outside class 'X' because it has a private identifier. (TS18013)
#typescript#javascript#oop#web-development

このエラーが発生する理由

このエラーは、ECMAScriptプライベートフィールド# プレフィックス)を使用している場合に発生します。TypeScript標準の private キーワードとは異なり、# 構文は「ハードなプライバシー」を強制します。つまり、JavaScriptエンジン自体が実行時にアクセスをブロックします。

TS18013が発生する主な原因は以下の通りです:

  • クラス定義の外にあるインスタンスから #field にアクセスしている。
  • サブクラスから親の #field を読み取ろうとしている。
  • (obj as any).#field を使ってプライバシーを回避しようとして、構文エラーが発生している。

解決策1:ゲッター経由でデータを公開する

最も確実な修正方法は、パブリックなゲッターを定義することです。これにより、内部状態を保護しつつ、外部コードが値を読み取るための制御された窓口を提供できます。

class User {
  #apiToken: string;

  constructor(token: string) {
    this.#apiToken = token;
  }

  // データの読み取り専用ビューを提供
  get maskedToken(): string {
    return `${this.#apiToken.substring(0, 4)}****`;
  }
}

const admin = new User("secret_9921_token");
// console.log(admin.#apiToken); // エラー TS18013
console.log(admin.maskedToken); // 動作する: "secr****"

解決策2:「ソフト」なプライバシーのために 'private' キーワードを使用する

誤った使用を防ぎたいだけで、ユニットテストなどのためにコードの柔軟性を保ちたい場合は、#private キーワードに置き換えます。TypeScriptの private は「ソフト」です。開発中にエラーをチェックしますが、JavaScriptにコンパイルされると消滅します。

class Config {
  // '#' の代わりに 'private' を使用
  private port: number = 8080;

  public getUrl() {
    return `http://localhost:${this.port}`;
  }
}

const cfg = new Config();
// cfg.port; // TSエラー。ただし # よりは制限が緩い

解決策3:サブクラス用に 'protected' に切り替える

プライベート識別子(#)は、子クラスからは完全に見えません。サブクラスが親のプロパティにアクセスする必要がある場合は、protected キーワードを使用する必要があります。なお、protected# 記号とは併用できないことに注意してください。

class Parent {
  // #internalValue = 10; // サブクラスからは参照不可
  protected sharedValue = 10; // サブクラスから参照可能
}

class Child extends Parent {
  logValue() {
    console.log(this.sharedValue); // 成功
  }
}

解決策4:ロジックをクラス内に移動する

このエラーは、クラス設計に不備があることを示唆している場合があります。データを外部に取り出して処理するのではなく、そのロジックをメソッド内に移動させます。これはオブジェクト指向プログラミングの「Tell, Don't Ask(尋ねるな、命じよ)」の原則に従ったものです。

// 非推奨:クラスの内部を直接参照する
// if (account.#balance > 100) { ... }

// 推奨:クラス自身に状態を管理させる
class Account {
  #balance: number = 500;

  public canAfford(amount: number): boolean {
    return this.#balance >= amount;
  }
}

クイック比較:# vs. private

  機能
  # 識別子
  private キーワード




  プライバシーレベル
  ハード(実行時)
  ソフト(コンパイル時)


  サブクラスからのアクセス
  不可
  不可(protectedを使用)


  'any' による回避
  不可能
  可能


  JavaScript出力
  #field として残る
  通常のプロパティになる

検証とテスト

エラーが解消されたか確認するには、npx tsc を実行してフルタイプチェックを行います。ゲッターを実装したり、可視性を private に変更したりした場合、VS Code などの IDE で赤色の下線がすぐに消えるはずです。実行時の検証については、ブラウザのコンソールを確認してください。外部から # フィールドにアクセスしようとすると、コードが実行される前に SyntaxError がスローされます。

プロのヒント

  • ユーザーに機密性の高い状態を触らせたくないライブラリの内部実装には # を使用します。
  • 標準的なアプリケーション開発では private を使い続けるのが無難です。ユニットテストの作成が大幅に容易になります。
  • 古いJavaScriptエンジンでは # フィールドの動作がわずかに遅くなることがありますが、現代の V8(Chrome/Node.js)では高度に最適化されています。

Related Error Notes