できない.dev

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

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

公開:

要約

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 に変わることを確認できる。

== versions ==
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
v20.20.2
Python 3.11.2
git version 2.39.5
 
                                                                               
                This is not the tsc command you are looking for                
                                                                               
 
To get access to the TypeScript compiler, tsc, from the command line either:
 
- Use npm install typescript to first add TypeScript to your project before using npx
- Use yarn to avoid accidentally running code from un-installed packages
v10.6.0
== run ==
--- TypeScript を install ---
Version 5.9.3
--- npx tsc (Property email does not exist を想定)---
src/bad.ts(3,18): error TS2339: Property 'email' does not exist on type '{ id: string; name: string; }'.
tsc 終了コード: 2
--- 解消: interface で必要なプロパティを明示する ---
tsc 終了コード: 0(0 なら解消)

— 2026-06-27 時点の出力

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