TypeScript | 基礎文法:変数・基本型 – 型エラーの典型パターン

TypeScript
スポンサーリンク

型エラーの「典型パターン」を知っておく意味

型エラーは無限にあるように見えて、実はよく出るパターンはかなり限られています。
この「典型パターン」を押さえておくと、エラーを見た瞬間に「ああ、これはあのパターンね」と当たりがつくようになります。
ここでは、初心者がほぼ確実に遭遇する代表的な型エラーを、例と一緒にかみ砕いて整理していきます。


パターン1: 「型Aは型Bに代入できません」系(is not assignable to)

もっとも頻出のエラー構文

まず、圧倒的に見る回数が多いのがこれです。

let age: number = 20;
age = "30";
TypeScript

このときのエラーはだいたいこうなります。

Type '"30"' is not assignable to type 'number'.

意味はシンプルで、「"30"(string)は number 型の場所には置けません」ということです。
この「is not assignable to」は、TypeScriptの型エラーの中核ワードだと思ってください。

関数の引数でも同じパターン

関数の引数でも同じ構造です。

function greet(name: string) {
  console.log(`Hello, ${name}`);
}

greet(123);
TypeScript

エラー:

Argument of type 'number' is not assignable to parameter of type 'string'.

ここでも、「number を string を期待している場所に渡しているからダメ」と言われています。
このパターンを見たら、必ず「期待されている型」と「実際に渡している型」の両方を見る癖をつけてください。


パターン2: プロパティが「ない」か「足りない」系

Property ‘xxx’ does not exist on type ‘YYY’

存在しないプロパティを触ろうとしたときの定番です。

const user = { name: "Taro" };

console.log(user.age);
TypeScript

エラー:

Property 'age' does not exist on type '{ name: string; }'.

これは、「{ name: string } という型には age なんてプロパティは定義されていないよ」という意味です。
オブジェクトの形(型)と、実際に触ろうとしているプロパティがズレているときに出ます。

Property ‘xxx’ is missing in type ‘AAA’ but required in type ‘BBB’

オブジェクトを代入するときに「足りない」パターンもよく出ます。

type User = {
  id: number;
  name: string;
};

const u: User = {
  id: 1
  // name がない
};
TypeScript

エラー:

Property 'name' is missing in type '{ id: number; }' but required in type 'User'.

User 型には name が必須なのに、今渡しているオブジェクトには name が missing(足りない)」という意味です。
このパターンを見たら、「型定義側で必須にしすぎていないか」「オブジェクト側で書き忘れていないか」を疑います。


パターン3: null / undefined かもしれない系

Object is possibly ‘null’ / ‘undefined’

これもかなりよく見るエラーです。

let name: string | null = null;

console.log(name.toUpperCase());
TypeScript

エラー:

Object is possibly 'null'.

「そのオブジェクト、null かもしれないのにメソッド呼んでない?」という警告です。
string | null のようなユニオン型を使っているときに、null チェックをせずに使おうとすると出ます。

対処としては、たとえばこうです。

if (name !== null) {
  console.log(name.toUpperCase());
}
TypeScript

この if の中では、TypeScript が「name はもう null じゃない」と理解してくれるので、エラーは消えます。
「null を許すなら必ずチェックする」「そもそも null を許さない設計にする」のどちらかを選ぶポイントです。


パターン4: ユニオン型との不一致系

許されていない値を入れようとしたとき

リテラル型+ユニオン型を使い始めると、次のようなエラーに出会います。

type Status = "success" | "error";

let s: Status = "success";
s = "pending";
TypeScript

エラー:

Type '"pending"' is not assignable to type '"success" | "error"'.

ここでも構造は同じです。

実際の型: "pending"
期待される型: "success" | "error"

つまり、「Status 型は success / error しか許していないのに、pending を入れようとしている」ということです。
「型の選択肢を増やすべきか」「代入している値が間違っているか」を考える場面になります。


パターン5: any が混ざって型安全が崩れる系

‘any’ type implicitly has an ‘any’ type など

strict 設定だと、暗黙の any に対してもエラーが出ます。

function greet(name) {
  console.log(`Hello, ${name}`);
}
TypeScript

エラー(例):

Parameter 'name' implicitly has an 'any' type.

「name の型が書かれていないから、暗黙に any になってしまっているよ」という警告です。
any は「何でも入るし、どこにでも代入できる」代わりに、型チェックをすり抜けてしまう危険な存在なので、基本は避けるべきです。

ここは素直にこう直します。

function greet(name: string) {
  console.log(`Hello, ${name}`);
}
TypeScript

「関数の引数には必ず型を書く」をルールにしてしまうと、この手のエラーはほぼ消えます。


パターン6: 戻り値の型と実際の return が合っていない系

Type ‘A’ is not assignable to type ‘B’(戻り値版)

戻り値の型注釈と、実際に返している値がズレているパターンです。

function getAge(): number {
  return "20";
}
TypeScript

エラー:

Type 'string' is not assignable to type 'number'.

ここでも、「string を number を期待している場所(戻り値)に置こうとしているからダメ」と言われています。
戻り値の型を変えるか、返している値の型を変えるか、どちらが正しい設計かを考える必要があります。


パターン7: this やコンテキストの型が合わない系(少し先の話)

これは少しレベルが上がりますが、クラスや this を使い始めると出てくるパターンです。

const obj = {
  value: 1,
  getValue() {
    return this.value;
  }
};

const fn = obj.getValue;
// fn(); // this の型が合わない、などのエラーになることがある
TypeScript

ここでは詳細には踏み込みませんが、「this の中身が何型だと推論されているか」がズレると、
Property 'value' does not exist on type 'XXX' のようなエラーが出ることがあります。

これは「this を素の関数に切り離して使わない」「アロー関数を使う」など、設計側で避けることも多いです。


型エラーを「パターン」で見る癖をつける

ここまで見てきたように、型エラーはだいたい次のどれかに分類できます。

型Aを型Bの場所に置こうとしている(assignable to 系)
オブジェクトの形が合っていない(プロパティがない・足りない)
null / undefined かもしれないものをそのまま使っている
ユニオン型の選択肢にない値を入れようとしている
any に逃げていて、型が曖昧になっている
戻り値の型注釈と実際の return がズレている

エラーを見たときに、
「これは assignable パターンだな」
「これは missing property パターンだな」
とラベルを貼る癖をつけると、直し方もすぐに見えてきます。

タイトルとURLをコピーしました