Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kenmori/3615c1f8d0f7cda8a0dc2b831b5b2783 to your computer and use it in GitHub Desktop.
Save kenmori/3615c1f8d0f7cda8a0dc2b831b5b2783 to your computer and use it in GitHub Desktop.
[TypeScript] ]index signature と Recordの空オブジェクトに対する違い

[TypeScript] ]index signature と Recordの空オブジェクトに対する違い

twitter

このような型付をみつけて

const a: Record<string, string> = { 
    doorToDoor: "delivery at door",
    airDelivery: "flying in",
    specialDelivery: "special delivery",
    inStore: "in-store pickup",
};

あれこれは {[key: string]: string} と同じ意味じゃないのか

なぜ、Recordを使っているのか...

と思い調べた.

結論

一緒。

Difference between index signature and Record for empty object?

要約すると

Record<string, string>{[key: string]: string} は同じで意味で わざわざRecord<string, string>と書くのは他の開発者を迷わせてしまうかもしれない ので {[key: string]: string}で書こうね。

As you note, K has a purpose... to limit the property keys to particular values.
If you want to accept all possible string-valued keys, you could do something like Record<string, T>,
but the idiomatic way of doing that is to use an index signature like { [k: string]: T }.

話はそれるが、 そもそも {[key: string]: string}は string値型を持っているならどんなkeyでも入ってしまうためよろしくない。

const a: Record<string, string> = { 
    doorToDoor: "delivery at door",
    airDelivery: "flying in",
    specialDelivery: "special delivery",
    inStore: "in-store pickup",
};
const aa:string = a["name"] // undefined

aaには実際はundefinedが入っていて、runtimeエラーになりそうだからだ

playground

なので上記の例でいうと、わかっている場合に限るが

type A = Record<"doorToDoor" | "airDelivery" | "specialDelivery" | "inStore", string>

const a: A = { 
    doorToDoor: "delivery at door",
    airDelivery: "flying in",
    specialDelivery: "special delivery",
    inStore: "in-store pickup",
};

の方が型安全で、他の追加keyを許さない。

Advance

このように書いたら?

type B = Record<"b" | "c", string>["b"]

// 当然BはT(string)

Recordは追加のkeyを完全に許さないのか

type B = Record<"b", string>

function b(obj: B){
    return obj
}

b({b: "b", c: "c"})// Error

リテラルはこの場合でもダメ

type B = Record<"b", string>

function b(obj: B){
    return obj
}

const imp = {b: "b", c: "c"}
b(imp) // ok TypeScriptのコンパイラは必須な値のみcheckする

function b(obj: B){
    return obj.c // ここで参照するとError
}
see: [excess properties](https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks)
// type B = Record<"b" | "c", string> で解決

参照

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment