💡

型 'string' のパラメーターを持つインデックス シグネチャが型Xに見つかりませんでした。ts(7053)

2025/02/11に公開

英語版の場合

  No index signature with a parameter of type 'string' was found on type 'X'

のエラーについて、意味が理解できなかったので初歩的なところから調査した。

インデックス シグニチャの言葉の意味

  • インデックス - 配列やオブジェクトの要素にアクセスするための識別子。添字のこと

  • シグニチャ - プログラミング上では、「メソッドや関数の定義情報」を表す。引数や戻り値が異なれば、同じメソッド名でも「ちがうシグニチャ」ということになる。

  • インデックス シグネチャ - 「どのような方法で要素にアクセスでき、その結果どのような型の値が得られるか」を定義する機能

インデックス シグネチャという機能

https://typescriptbook.jp/reference/values-types-variables/object/index-signature
にあるように

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