1. ホーム
  2. casting

[解決済み] タイプスクリプト 型にインデックス署名がありません

2022-03-02 22:11:59

質問

欲しいもの MyInterface.dic 辞書のような存在になるために name: value は、次のように定義しています。

interface MyInterface {
    dic: { [name: string]: number }
}

ここで、私の型を待つための関数を作成します。

function foo(a: MyInterface) {
    ...
}

そして入力です。

let o = {
    dic: {
        'a': 3,
        'b': 5
    }
}

私が期待しているのは foo(o) が正しいのに、コンパイラが落ちます。

foo(o) // Typescript error: Index signature is missing in type { 'a': number, 'b': number }

可能なキャスティングがあることは知っています。 let o: MyInterface = { ... } を使えばいいのですが、問題があります。 なぜ typescript が私の型を認識しないのですか?


おまけ:以下の場合は正常に動作します。 o がインラインで宣言されている。

foo({ 
  dic: {
    'a': 3, 
    'b': 5
  }
})

解決方法は?

問題は、型を推論する際に o があります。

{ dic: { a: number, b: number } }

とは違うんです。 { dic: { [name: string]: number } } . 重要なのは、トップの署名では、次のようなことは許されないということです。 o.dic['x'] = 1 . 2番目の署名では、そうなります。

しかし、TypeScriptの安全性の大部分は、これらが同じではないこと、そしてオブジェクトを辞書として扱うことが明示的に意図されていることが分かっている場合にのみ、辞書として扱わせるという事実に由来している。これによって、オブジェクトに存在しないプロパティを誤って読み書きすることを防いでいるのです。

解決策は、TypeScriptが辞書として意図されていることを確実に把握することだ。つまり

  • 辞書であることを示す型をどこかで明示的に提供する。

    let o: MyInterface

  • インラインで辞書であることを主張する。

    let o = { dic: <{ [name: string]: number }> { 'a': 1, 'b': 2 } }

  • TypeScriptが推論する初期型であることを確認する。

    foo({ dic: { 'a': 1, 'b': 2 } })

TypeScriptが2つのプロパティを持つだけの普通のオブジェクトだと思い込んでいて、後で辞書として使おうとすると不幸になるケースがあるんだ。