🔍

TypeScriptでブラケット記法を使うときにハマったこと

2021/09/16に公開

はじめに

ブラケット記法でプロパティへアクセスしようとしたら「Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'xxx'. No index signature with a parameter of type 'string' was found on type 'xxx'」のエラーが出ました。
対応について整理しました。

やってみたこと

エラーの再現

エラーになった時のソースはこんな感じでした。

interface FruitsName {
  name_ja:      string;
  name_en:     string;
}

const apple = {
  name_ja: "りんご",
  name_en: "apple",
} as FruitsName;

const key: string = 'name_en';
const appleName: string = apple[key]; // ここでエラー: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'FruitsName'. No index signature with a parameter of type 'string' was found on type 'FruitsName'.

次のエラーが出ます

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'FruitsName'. No index signature with a parameter of type 'string' was found on type 'FruitsName'.
Playgroundで動かした時のスクショ

状況の整理

  • まずは英語が読めなかったのでgoogle翻訳してみました
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'FruitsName'. No index signature with a parameter of type 'string' was found on type 'FruitsName'.

タイプ「string」の式を使用してタイプ「FruitsName」にインデックスを付けることはできないため、要素には暗黙的に「any」タイプがあります。タイプ「文字列」のパラメータを持つインデックス署名がタイプ「FruitsName」で見つかりませんでした。

次のように理解しました。
FruitsNameに存在しないキーを指定してしまう可能性があるため問題がある、なぜなら、string型でキーを指定されるため。

つまり問題はFruitsNameに存在しないキーを指定しうることだと思いました。

そこで、 keyofを利用して問題を解決してみることにしました。

keyにkeyofを指定

interface FruitsName {
  name_ja:      string;
  name_en:     string;
}

const apple = {
  name_ja: "りんご",
  name_en: "apple",
} as FruitsName;

const key: keyof FruitsName = 'name_en';
const appleName: string = apple[key]; 

エラーが出なくなりました。

keyに「FruitsNameに存在しないキー」を入れてみる

interface FruitsName {
  name_ja:      string;
  name_en:     string;
}

const apple = {
  name_ja: "りんご",
  name_en: "apple",
} as FruitsName;

const key: keyof FruitsName = 'name'; // Type '"name"' is not assignable to type '"name_ja" | "name_en"'.
const appleName: string = apple[key]; 

ちゃんとエラーが出ます。

Type '"name"' is not assignable to type '"name_ja" | "name_en"'.
Playgroundで動かした時のスクショ

参考

Discussion