8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【TypeScript】ObjectのKeyに変数でアクセスする

Posted at

1. はじめに

こんにちは!みなさま楽しいプログラミンライフをお過ごしでしょうか?
最近TypeScriptでのReact開発を勉強しています。

ObjectのKeyに変数でアクセスしようとしたときに、
型付けのところでハマったポイントがあったので、備忘録として残しておきたいと思います。

Version
node.js 14.12.0
yarn 1.22.7
TypeScript 3.8.3

2. やりたいこと

以下のような、
object2のcategoryのvalueと、object1のkeyが一致するvalueの配列に、object2をまるっとpushしたい。object3のようになるイメージ。

const object1 = {
  category1: [],
  category2: []
}

const object2 = {
  id: 1,
  title: "nazeudon",
  category: "category1",
}

const object3 = {
  category1: [
    {
      id: 1,
      title: "nazeudon",
      category: "category1",
    },
  ],
  category2: []
}

3. JavaScriptだとこう書ける

とてもシンプル。まさに。Simple is the Best.

const cat = object2.category;
object1[cat].push(object2);

4. ハマったポイント

同じことをTypeScriptでやろうとすると。。。

const cat = object2.category;
object1[cat].push(object2);

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ category1: never[]; category2: never[]; }'.
No index signature with a parameter of type 'string' was found on type '{ category1: never[]; category2: never[]; }'.(7053)

要素は暗黙のうちに 'any' 型を持っています。なぜなら、型 'string' の式は型 '{ category1: never[]; category2: never[]; }' をインデックス化するために使用できないからです。
type '{ category1: never[]; category2: never[]; }' には、型 'string' のパラメータを持つインデックスシグネチャが見つかりませんでした。

そりゃ、TypeScriptだからね。型付けしろと言うわけですよね!
interfaceで型付けしてやって〜、でも。。。

interface OBJECT1 {
  category1: OBJECT2[]
  category2: OBJECT2[]
}

interface OBJECT2 {
  id: number
  title: string
  category: string
}

const object1: OBJECT1 = {
  category1: [],
  category2: []
}

const object2: OBJECT2 = {
  id: 1,
  title: "nazeudon",
  category: "category1",
}

const cat = object2.category;
object1[cat].push(object2);

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

要素は暗黙のうちに 'any' 型を持っていますが、それは 'string' 型の表現が型 'OBJECT1' のインデックスに使用できないからです。
型 'OBJECT1' の型 'string' のパラメータを持つインデックス・シグネチャは見つかりませんでした。

おっと、これでもダメなのね。OBJECT1のインデックスにString型を指定できないと言われています。

ってことで、この解決に小一時間費やしたので、解決策を残しておきます。

5. TypeScriptでの書き方(例)

const cat: keyof OBJECT1 = object2.category as keyof OBJECT1;
object1[cat].push(object2);

こんな感じで、cat変数とobject2.categoryを共に、OBJECT1のkeyですよ、と明示してあげれば無事動きました!!

6. 最後に思ったこと

  • 自分のわかっている知識の範囲だと、型付けはバグを防げて便利だなと言う印象。
  • 自分のわからない範囲の知識が必要で、型に起因するエラーが出ると、型付けめんどくさ!ってなる。
  • 結論、もっと勉強しましょう。今回も良い勉強になりました。
8
6
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
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?