【TypeScript】ブランケット記法で値にアクセスする際のエラーを解決

今回はTypeScriptでブランケット記法を使うときに出くわすエラーについて紹介しますね。

お題となるエラーはこれです。

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'UserType'. No index signature with a parameter of type 'string' was found on type 'UserType'.

(訳)'string' 型の式は 'UserType' 型のインデックスに使用できないため、要素は暗黙的に 'any' 型を持ちます。タイプ「string」のパラメータを持つインデックス署名がタイプ「UserType」で見つかりませんでした。

そして結論は、Keyに指定する文字列の型をしっかり指定してあげましょうねです。

エラーと出会っちゃうコード

今回のTypeScriptエラーは要するに、ブランケット記法のキーに文字列(String)を指定してオブジェクトの値を取り出そうとした場合に発生するわけです。

例えばこんなコード。

type UserType = {
 name: string
 age: number
};

const user: UserType = {
 name: "John",
 age: 30
};

function printUserProperty() {
 const keys = ['name', 'age']
 keys.some((key) => console.log(user[key])) // ここでエラーが発生
}

userオブジェクトにUserTypeという型付がされている状態。

関数の中ではuserオブジェクトのキーである'name''age'が配列になっていて、順番にkeyとして呼び出されてconsole.log(user[key])でオブジェクトの値を出力してます。

これを実行するとエラーが発生

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'UserType'. No index signature with a parameter of type 'string' was found on type 'UserType'.

(訳)'string' 型の式は 'UserType' 型のインデックスに使用できないため、要素は暗黙的に 'any' 型を持ちます。タイプ「string」のパラメータを持つインデックス署名がタイプ「UserType」で見つかりませんでした。

このエラーが言いたいのはつまりこういうことです

TypeScriptくん

user[key]でオブジェクトの値を取り出したいんだろうけど、keyの情報が少ないよ。

userオブジェクトのキーは'name'と'age'だけ。

keyがstring型であることはわかるけどそれが'name'と'age'である保証はないよね?どんな値が渡ってくるかわからん。定義してくれ。

はいはい。なので言われた通りkeyに型付してあげましょ。

function printUserProperty() {
  const keys: (keyof UserType)[] = ['name', 'age']; // keysの型を明示
  keys.some((key) => console.log(user[key])); // 型のエラーが解消
}

keyofはTypeScriptの演算子で、オブジェクトの型からプロパティ名(キー名)を取り出せます。

UserType型はnameとageの2つのプロパティを持ってるので、keyof UserType = "name" | "age"です。

これでどうでしょう?TypeScriptくん

TypeScriptくん

keyの型を明確にしてくれてありがと!
keyに渡ってくるのは'name'か'age'なんだね。どちらもUserTypeのプロパティに存在するから、ちゃんと値を取り出せそうだよ👌

よかった、解決です。

keyof型演算子

TypeScriptについての解説は「サバイバルTypeScript」というサイトが一番わかりやすいです。
keyof型演算子は非常によく使うので今日のうちに覚えちゃいましょ

keyof型演算子|サバイバルTypeScript

型アサーションを使う方法

さっきの以外だと、asを使った型アサーションを使った書き方もできますね。結局keyof型演算子を使います

function printUserProperty() {
  const keys = ['name', 'age'];
  keys.some((key) => console.log(user[key as keyof UserType])); // 型アサーションを使用
}

アサーション(訳:主張する)は要するに、TypeScriptくんが「keyにどんな値が渡ってくるかわからん...」という時に、「keyの型はこれだよ!私を信じて!」と主張するための記法です。

TypeScriptくん

keyにどんな値が渡ってくるか分からなくて不安だけど、
key as keyof UserTypeってことは、きっと'name''age'しか渡ってこないんだろうな、、、ボク信じるよ!

おしまい。

コメントを残す

CAPTCHA