Code Fix

中級

union型(string | number)のメソッド呼び出しで型エラーになる理由

string | numberのようなunion型の値に対して、片方の型にしか無いメソッド(toUpperCaseなど)を呼び出そうとすると、もう一方の型に無いことを理由にエラーになります。typeof等で型を絞り込む(narrowing)必要があります。

エラーメッセージの読み方

main.ts(2,16): error TS2339: Property 'toUpperCase' does not exist on type 'string | number'.
main.ts
ファイル名
2
行番号
16
列番号 — この位置でtscが検査に失敗しました
TS2339
エラーコード — 検索するとTypeScriptの解説が見つかります
Property 'toUpperCase' does not exist on type 'string | number'.
内容 — 期待していたもの、または受け付けられなかったもの

このエラーが出る典型パターン

パターン1

 1  function describe(value: string | number): string {
 2    return value.toUpperCase();
                        ^
 3  }
 4  console.log(describe("hi"));
main.ts(2,16): error TS2339: Property 'toUpperCase' does not exist on type 'string | number'.

valueはstring | number型です。toUpperCaseはstringにしかないメソッドなので、narrowingせずには呼べません。

直し方: toUpperCase を toString にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  function format(value: string | number): string {
 2    return value.toFixed (2);
                       ^
 3  }
 4  console.log(format(3.14159));
main.ts(2,16): error TS2339: Property 'toFixed' does not exist on type 'string | number'.

toFixedはnumberにしかないメソッドです。string | number型のままでは呼び出せません。

直し方: toFixed を toString にします。

この問題を解いてみる →

パターン3

 1  function label(value: string | boolean): string {
 2    return value.toUpperCase();
                        ^
 3  }
 4  console.log(label(true));
main.ts(2,16): error TS2339: Property 'toUpperCase' does not exist on type 'string | boolean'.

toUpperCaseはbooleanには存在しません。string | boolean型のままでは呼び出せません。

直し方: toUpperCase を toString にします。

この問題を解いてみる →

パターン4

 1  function tag(value: string | number): string {
 2    return value.toUpperCase();
                        ^
 3  }
 4  console.log(tag("hi"));
main.ts(2,16): error TS2339: Property 'toUpperCase' does not exist on type 'string | number'.

valueはstring | number型です。toUpperCaseはstringにしかないメソッドなので呼べません。

直し方: toUpperCase を toString にします。

この問題を解いてみる →

パターン5

 1  function fmt(value: number | boolean): string {
 2    return value.toFixed (2);
                       ^
 3  }
 4  console.log(fmt(3.14159));
main.ts(2,16): error TS2339: Property 'toFixed' does not exist on type 'number | boolean'.

toFixedはnumberにしかないメソッドです。number | boolean型のままでは呼び出せません。

直し方: toFixed を toString にします。

この問題を解いてみる →

よくある誤解

「文字列を渡すつもりだから大丈夫」という呼び出し側の意図は、TypeScriptの型チェックには伝わりません。union型のまま扱う限り、tscは「numberが渡されるかもしれない」という前提でチェックします。

実務での勘所

typeofによる絞り込みが型として認識される仕組みを応用すると、union型に新しいメンバーを追加し忘れた場合の検出にも使えます。すべての分岐を書き終えた後のelseの中で、その変数をnever型の変数に代入するコードを書いておくと、将来union型に新しい型が追加されたのに対応する分岐を書き忘れた場合、絞り込みが完了せずnever型に代入できなくなり、コンパイルエラーとして知らせてくれます。この「neverへの代入」を使った網羅性チェックは、TypeScriptでよく使われる実務のテクニックです。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)