MeWrite Docs

TS2339: Property 'x' does not exist on type 'Y'

TypeScriptで型に存在しないプロパティにアクセスした際のエラー

概要

TypeScriptで、ある型に定義されていないプロパティにアクセスしようとした際に発生するコンパイルエラーです。

エラーメッセージ

TS2339: Property 'x' does not exist on type 'Y'.

原因

  1. 型定義の不足: オブジェクトの型にプロパティが定義されていない
  2. 型の絞り込み不足: Union型やunknown型を適切に絞り込んでいない
  3. オプショナルプロパティ: プロパティがundefinedの可能性がある
  4. APIレスポンスの型: 外部APIのレスポンス型が不完全

解決策

1. インターフェースにプロパティを追加

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Bad
interface User {
  name: string;
}

const user: User = { name: 'John', age: 30 }; // Error
console.log(user.age); // TS2339

// Good
interface User {
  name: string;
  age: number;
}

const user: User = { name: 'John', age: 30 };
console.log(user.age); // OK

2. 型ガードで絞り込む

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
interface Dog {
  bark(): void;
}

interface Cat {
  meow(): void;
}

type Pet = Dog | Cat;

// Bad
function makeSound(pet: Pet) {
  pet.bark(); // TS2339: Property 'bark' does not exist on type 'Pet'
}

// Good: in演算子で型ガード
function makeSound(pet: Pet) {
  if ('bark' in pet) {
    pet.bark();
  } else {
    pet.meow();
  }
}

3. Optional ChainingとNullish Coalescing

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
interface Response {
  data?: {
    user?: {
      name?: string;
    };
  };
}

// Bad
const name = response.data.user.name; // TS2339

// Good
const name = response.data?.user?.name ?? 'Unknown';

4. 型アサーション(慎重に使用)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
interface ExtendedWindow extends Window {
  customProperty: string;
}

// Good: 型アサーション
const customValue = (window as ExtendedWindow).customProperty;

// Better: 型ガード付き
if ('customProperty' in window) {
  const customValue = (window as ExtendedWindow).customProperty;
}

5. Record型やインデックスシグネチャ

1
2
3
4
5
6
7
8
// 動的なキーを持つオブジェクト
interface DynamicObject {
  [key: string]: unknown;
}

const obj: DynamicObject = { foo: 'bar' };
console.log(obj.foo); // OK
console.log(obj.anyKey); // OK

6. APIレスポンスの型を定義

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Bad: any型を使用
const response = await fetch('/api/user');
const data = await response.json();
console.log(data.name); // 型安全ではない

// Good: 型を定義
interface ApiResponse {
  id: number;
  name: string;
  email: string;
}

const response = await fetch('/api/user');
const data: ApiResponse = await response.json();
console.log(data.name); // 型安全

7. Discriminated Unions

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
interface SuccessResponse {
  status: 'success';
  data: { id: number };
}

interface ErrorResponse {
  status: 'error';
  message: string;
}

type ApiResponse = SuccessResponse | ErrorResponse;

function handleResponse(response: ApiResponse) {
  if (response.status === 'success') {
    console.log(response.data.id); // OK: 型が絞り込まれる
  } else {
    console.log(response.message); // OK
  }
}

よくある間違い

  • as anyで型エラーを無視する(型安全性が失われる)
  • 外部ライブラリの型定義が古い場合に気づかない
  • JSON.parse()の戻り値をそのまま使用する

関連エラー

参考リンク

TypeScript の他のエラー

最終更新: 2025-12-13