型 'string' のパラメーターを持つインデックス シグネチャが型Xに見つかりませんでした。ts(7053)
英語版の場合
No index signature with a parameter of type 'string' was found on type 'X'
のエラーについて、意味が理解できなかったので初歩的なところから調査した。
インデックス シグニチャの言葉の意味
-
インデックス - 配列やオブジェクトの要素にアクセスするための識別子。添字のこと
-
シグニチャ - プログラミング上では、「メソッドや関数の定義情報」を表す。引数や戻り値が異なれば、同じメソッド名でも「ちがうシグニチャ」ということになる。
-
インデックス シグネチャ - 「どのような方法で要素にアクセスでき、その結果どのような型の値が得られるか」を定義する機能
インデックス シグネチャという機能
にあるように
TypeScriptで、オブジェクトのフィールド名をあえて指定せず、プロパティのみを指定したい場合があります。そのときに使えるのがこのインデックス型(index signature)です。
let obj: {
[K: string]: number;
};
※ Kの文字はなんでもOK
エラー文を分解して読み解く
このエラーが起きるサンプルコードを以下に定義する。
// 厳密な型定義を持つオブジェクト
interface Languages {
readonly ja: {
greeting: string;
farewell: string;
};
readonly en: {
greeting: string;
farewell: string;
};
}
// 定義されたオブジェクト
const messages: Languages = {
ja: {
greeting: 'こんにちは',
farewell: 'さようなら'
},
en: {
greeting: 'Hello',
farewell: 'Goodbye'
}
};
// エラーを引き起こすコード
function getGreeting(locale: string) {
return messages[locale].greeting; // ここでエラーが発生
}
型 'string' のパラメーターを持つインデックス シグネチャが型Languagesに見つかりませんでした。
型 'string' のパラメーターを持つインデックス シグネチャが
= キー名の型がstringである型定義が
型Languagesに見つかりませんでした。
= Languages型に見つかりません。
今回のコードを見ると、Languages型のキー名はstringというゆるい制約ではなく今回の場合 en|ja
に制限されている。localeはstringなので、型が不一致。コードを以下のように変えると、エラーはなくなる。
function getGreeting(locale: 'en' | 'ja') {
return messages[locale].greeting; // エラーでなくなる
}
【結論】エラー文を言い換えると
messages[locale]
に波線が引いてあり、Languages型には、キー名がstring型になっている「インデックスシグネチャ」がありません。
が表示されているとき
=
今messages
にアクセスしようとしている locale
の型はstringですが、型の不一致があるためmessages(Languages型)はキーがstringでアクセスできません。今回の場合、localeの型がゆるすぎるのでより厳密にLanguages型にあうように('en'|'ja')定義しなおしてね!
読み返してエラー文だけでは理解できないですね、、、
どうやって直すか
①以下のようにlocaleの型をmessagesに合わせてあげる
function getGreeting(locale: 'en' | 'ja') {
return messages[locale].greeting; // エラーでなくなる
}
②Languagesの型をゆるくする。これは良くないきがする
interface Languages {
[key: string]: {
greeting: string;
farewell: string;
};
}
③型アサーションを使用。これもイマイチ
function getGreeting(locale: string) {
return (messages as any)[locale].greeting;
}
Discussion