TypeScriptのIndex Signatureでプロパティに制限をかけたかったので、今更ながらよくよく調べてみた

目次

Index Signatureを使用することでプロパティの型を指定することができる。

例えば、

interface BodyType {
    [key: number]: {
        min: number,
        max: number
    }
}

const body:BodyType = 
    {
        String: {
            min: 0,
            max: 230
        },
        1: {
            min:0,
            max:300
        }
    }


console.log(body.String.min)}
]

上記のようにnumber型という風に明示的に宣言することで、Stringという文字列をkeyに指定したことでエラーを吐かせることが可能である。

type '{ hello: { min: number; max: number; }; 1: { min: number; max: number; }; }' is not assignable to type 'BodyType'.
  Object literal may only specify known properties, and 'hello' does not exist in type 'BodyType'.

逆にIndex Signatureを文字列という風に明示的に宣言することで、1というKeyがエラーを吐きそうだが、

This is because when indexing with a number, JavaScript will actually convert that to a string before indexing into an object

という風に文字列にしてからアクセスするので問題ないということで、エラーは出ない。

Index Signatureでは特定の文字列を持つプロパティのみを制約することはできない

じゃあ、keyが特定の文字列のみの場合はどうすればいいか?

interface BodyType {
    [key in 'a' | 'b']: {
        min: number,
        max: number
    }
}

上記の記述すると、

A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.

というエラーが出る。

エラーが出たコードを実現しようとすると

interface Content {
    min: number,
    max: number
}
interface BodyType {
    a: Content,
    b: Content
}

という風に記載することで解決できる。

そもそもIndex Signatureの定義が

Sometimes you don’t know all the names of a type’s properties ahead of time, but you do know the shape of the values.

という風に型のプロパティ名を事前にすべて把握していない場合に使用する物なので、そもそも実現しようとしていることが間違え。

間違えだけれど、ちなみに、Typeを使用することで、上記のような書き方で実現することができる。

type BodyType = {
    [key in 'a' | 'b' | 'c']: {
        min: number,
        max: number
    }
}

InterfaceとTypeの違いは別で調べたい。

次に読むおすすめ記事

TypeScriptのIndex Signatureでプロパティに制限をかけたかったので、今更ながらよくよく調べてみた

TypeScriptで定義済みの型からプロパティを取り出し新しい型を作る方法

この記事に対するコメント

お気軽にコメントを下さい

メールアドレスが公開されることはありません。 が付いている欄は必須項目です