web-dev-qa-db-ja.com

Typescript:オブジェクトのすべてのプロパティは同じ型でなければならないことを宣言します

TypeScriptでは、配列内のすべての要素が次のように同じ型であることを宣言できます。

const theArray: MyInterface[]

オブジェクトのすべてのプロパティ値が同じ型でなければならないことを宣言することができる同様のものはありますか? (すべてのプロパティ名を指定せずに)

たとえば、私は現在これをやっています:

interface MyInterface {
    name:string;
}

const allTheThingsCurrently = {
    first: <MyInterface>{name: 'first thing name' },
    second: <MyInterface>{name: 'second thing name' },
    third: <MyInterface>{name: 'third thing name' },
    //...
};

...すべての単一のプロパティに対して<MyInterface>を指定する方法に注意してください。このためのショートカットはありますか?つまり、私はこのようなものを想像しています...

const allTheThingsWanted:MyInterface{} = {
    first: {name: 'first thing name' },
    second: {name: 'second thing name' },
    third: {name: 'third thing name' },
    //...
};

MyInterface{}は無効なコードの部分です。冗長性を減らし、オプションで他のプロパティが異なる型のオブジェクトに追加されないようにする特別な厳密さを実現する方法を探しています。

6
LaVache

ジェネリックを使用して、必要なプロパティタイプを指定します。

type SamePropTypeOnly<T> = {
  [P: string]: T;
}

interface MyInterface {
  name: string;
}

const newObj: SamePropTypeOnly<MyInterface> = {
  first: { name: 'first thing name' },
  second: { name: 'second thing name' },
  third: { name: 'third thing name' },
  // forth: 'Blah' // Type 'string' is not assignable to type `MyInterface`
}
1
am0wa

ソリューション1: インデックス可能なタイプ

interface Thing {
  name: string
}

interface ThingMap {
  [thingName: string]: Thing
}

const allTheThings: ThingMap = {
  first: { name: "first thing name" },
  second: { name: "second thing name" },
  third: { name: "third thing name" },
}

ここでの欠点は、allTheThings以外のプロパティにエラーなしでアクセスできることです。

allTheThings.nonexistent // type is Thing

これは、ThingMap[thingName: string]: Thing | voidとして定義することでより安全にできますが、そこにあることがわかっているプロパティにアクセスしている場合でも、至る所でnullチェックが必要になります。

解決策2:何もしない関数を持つジェネリック

const createThings = <M extends ThingMap>(things: M) => things

const allTheThings = createThings({
  first: { name: "first thing name" },
  second: { name: "second thing name" },
  third: { name: "third thing name" },
  fourth: { oops: 'lol!' }, // error here
})

allTheThings.first
allTheThings.nonexistent // comment out "fourth" above, error here

createThings関数には汎用のMがあり、すべての値がMである限り、Thingは何でもかまいません。そうするとMが返されます。オブジェクトを渡すと、オブジェクトはextendsの後の型に対して検証され、渡されたものと同じ形状が返されます。

これは「最もスマートな」ソリューションですが、多少巧妙に見えるハックを使用して実際に機能させます。いずれにしても、TSがこのようなケースをサポートするためのより良いパターンを追加するまでは、これが私の推奨ルートです。

14
kingdaro