0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScriptで、オブジェクトに対して動的にキーアクセスしたい

Posted at

はじめに

JavaScript→TypeScriptへ移行する際に、オブジェクトに対するアクセスで型チェックエラーが出て困っていました。

const obj = {
    key1: "hoge",
    key2: "fuga",
    key3 : ""
}
// →
// const obj: {
//     key1: string;
//     key2: string;
//     key3: string;
// }
// が型推論される

const objArray: string[] = [];

// 型チェックエラーが発生する
for (let i = 1; i <= 3; i++) {
    if (obj[`key${i}`]) {
        objArray.push(obj[`key${i}`]);
    }
}
console.log(objArray);

objにはkey1, key2, key3のキーしか存在しないため、obj[`key${i}`]という形でアクセスしようとすると、コンパイルエラーになります。

error TS7053: Element implicitly has an 'any' type because expression of type 'key${number}' can't be used to index type '{ key1: string; key2: string; key3: string; }'.

上記の場合では for文中でiは1, 2, 3のいずれかに限られますが、TypeScriptではそこまで反映しての型チェックはできないです。
今回に限らず、TypeScriptの型チェックは必ずしも完璧ではないことに留意しましょう。
今回も、存在しないプロパティにアクセスする可能性があるためにエラーが発生しています。

対策1

type Obj = {
    [key: `key${number}`]: string;
}
const obj: Obj = {
    key1: "hoge",
    key2: "fuga",
    key3 : ""
}

const objArray: string[] = [];
for (let i = 0; i <= 3; i++) {
    if (obj[`key${i}`]) {
        objArray.push(obj[`key${i}`]);
    }
}
console.log(objArray);

[key: `key${number}`]: string;といったインデックス型を用いて、型定義してあげればいいのではないかと思い、上記コードを書きました。

型チェックは問題なく突破できるものの、

  • 型定義をしなければいけないのでコード量が増えてしまう
  • 実際には存在しないキー(key4など)へのアクセスも型定義上できてしまう
// TypeScriptでの型チェックは通るがランタイムエラーが発生する
console.log(obj.key4);

といったデメリットがあり、ベストな回答とは言えない気がします。

対策2

悩んだ結果、下記コードに辿り着きました。
Object.keys()やObject.values()を用いることで、オブジェクトに対する安全な動的アクセスが可能です。
型チェックに引っ掛かることも、型安全性が破壊されランタイムエラーが発生することもないです。

const obj = {
    key1: "hoge",
    key2: "fuga",
    key3 : ""
}

const objArray = Object.values(obj).filter(value => value);
console.log(objArray);

参考文献

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?