web-dev-qa-db-ja.com

TypeScript:文字列を使用する場合、インデックス署名パラメーターは「文字列」または「数値」でなければなりません。数

配列を正規化する関数を作成しようとしていますが、次のような構造の出力オブジェクトが必要です。

{
  allIds: [1],
  byId: {
    1: {...}
  }
}

OR

{
  allIds: ['1'],
  byId: {
    '1': {...}
  }
}

これに対応するために、IOutputというインターフェイスを作成しようとしています。

私はこれを試しました:

interface IOutput {
  allIds: string[] | number[]
  byId: {
    [key: number | string]: any
  }
}

しかし、それは私に次のエラーを与えます

インデックスシグネチャのパラメータータイプは 'string'または 'number'でなければなりません。 ts(1023)

私がこれを行うとうまくいくようです:

interface IOutput {
  allIds: string[] | number[]
  byId: {
    [key: number]: any
  }
}

OR

interface IOutput {
  allIds: string[] | number[]
  byId: {
    [key: string]: any
  }
}

しかし、それは私が達成しようとしていることではありません。私もこれを試しましたが、同じエラーが発生します:

type StringOrNumber = string | number

interface IOutput {
  allIds: string[] | number[]
  byId: {
    [key: StringOrNumber ]: any
  }
}

私がやろうとしていることをどのように達成できますか?

8

これは、インデックスを書き込む現在の方法の制限です(これにより すぐに が変更されます)。インデックスシグネチャパラメーターは、numberまたはstringのみにすることができます(これらの型ではなく、それらの和集合ではなく、リテラル型ではありません)。ただし、number用とstring用の2つのインデックスシグネチャを持つことができます。

別の簡単な方法があります。string署名がある場合は、実際にnumberでもインデックスを作成できます。つまり、これは、stringインデックスとnumberインデックスの戻り値の型が同じ場合、文字列インデックスが必要なことを意味します

interface IOutput {
    allIds: string[] | number[]
    byId: {
        [key: string]: any
        // [key: number]: any // Valid but not necessary
    }
}

let o: IOutput = {
    allIds: [1],
    byId: {
        1: {}
    }
}
let o2: IOutput = {
    allIds: ['1'],
    byId: {
        '1': {}
    }
}