このエラーが発生する理由
このエラーは、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)では高度に最適化されています。

