できない.dev

TypeScript で「Property does not exist on type」が解消できない

Property 'x' does not exist on type 'Y' は実装より型定義が狭い時に出る。
interface 拡張・型ガードでの絞り込み・宣言マージなど、原因に応じて使い分ける。

公開: 更新:

実行例あり(2026-08-02 に実環境で検証)

要約

Property 'x' does not exist on type 'Y'.実装が知っているが型定義が知らないプロパティ にアクセスしたときに出る。
「型がそもそも狭い」「ユニオン型で絞り込んでいない」「宣言が無い」のどれかを切り分け、対応する書き方を選ぶ。

よくある原因

  1. 型を明示していない: const user = await res.json() の戻り値が any ではなく狭い型に推論され、必要なプロパティが含まれていない
  2. ユニオン型のまま参照: type Shape = Circle | Squareshape.radius を読むと、Square に無いため拒否される(Narrowing 公式(新しいタブで開く)
  3. 型定義ファイル不在: import x from "old-lib"old-lib.d.ts が無く anyunknown 型になる
  4. グローバル拡張の不足: window.MY_APP = ... のようにグローバル変数を追加したが、declare global で型を足していない

解決策

1. 型を明示する

interface User {
  id: string;
  name: string;
  email: string;
}
 
async function fetchUser(): Promise<User> {
  const res = await fetch("/api/me");
  return (await res.json()) as User;
}

Object Types 公式ハンドブック(新しいタブで開く) のとおり、interfacetype で必要なプロパティを宣言する。
受け取った値はまず unknown に置き、型ガードで絞り込むとより安全。

2. ユニオン型は絞り込んでから読む

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; size: number };
 
function area(s: Shape) {
  if (s.kind === "circle") {
    return Math.PI * s.radius ** 2;   // Circle に絞られる
  }
  return s.size * s.size;
}

判別可能ユニオン(discriminated union)にしておくと switchif で型が確定する。
詳細は 型の絞り込み を参照。

3. 型未提供パッケージに対応する

npm install --save-dev @types/lodash

公式型定義が無いなら自前で書く。
プロジェクトに types/old-lib.d.ts を作成し、tsconfig.jsoninclude に含める。

declare module "old-lib" {
  export function legacyFn(input: string): number;
}

4. global を拡張する

// src/types/global.d.ts
export {};
 
declare global {
  interface Window {
    MY_APP: { version: string };
  }
}

宣言マージ公式(新しいタブで開く) のとおり、interface は同名で複数回書くと自動でマージされる。tsconfig.jsonincludesrc/types/** が含まれているかも確認する。

実行例

実際に上記の手順を node:20 環境で動かすと、email プロパティを持たない型への参照が error TS2339 としてコンパイラに検出され、interface で正しく宣言し直すことで終了コード 0 に変わることを確認できる。

Version 5.9.3
$ npx tsc
src/bad.ts(3,18): error TS2339: Property 'email' does not exist on type '{ id: string; name: string; }'.
tsc 終了コード: 2
$ npx tsc
tsc 終了コード: 0(0 なら解消)

— 2026-08-02 時点の出力

検証環境

検証日
実行環境
node:20

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

この記事は役立ちましたか?