TypeScript インターフェース: どちらか一方の属性を必須にする2つの方法
TypeScript インターフェースで「どちらか一方」の属性を必須にする方法
この場合、以下の2つの方法で実現できます。
never 型を使用する
never
型は、決して存在しない値を表す型です。この型を利用して、以下の方法で「どちらか一方」の属性を必須にできます。
interface MyInterface {
// どちらか一方の属性
firstProperty?: string;
secondProperty?: number;
// どちらか一方の属性が必須であることを示す
[key: string]: firstProperty extends never ? secondProperty : never;
}
このコードでは、firstProperty
と secondProperty
という2つの属性を定義しています。
そして、[key: string]: ...
という構文を使って、インターフェースのすべての属性に対して、以下の条件を適用しています。
firstProperty
がnever
型の場合、secondProperty
が必須になる。
この方法を使うことで、どちらか一方の属性が必ず存在することを TypeScript に対して明示的に伝えることができます。
Partial 型と Required 型を使用する
Partial
型は、すべての属性をオプションにする型です。Required
型は、すべての属性を必須にする型です。
これらの型を利用して、以下の方法で「どちらか一方」の属性を必須にできます。
type FirstProperty = {
firstProperty: string;
};
type SecondProperty = {
secondProperty: number;
};
type MyInterface = Partial<FirstProperty> & Partial<SecondProperty>;
// どちらか一方の属性が必須であることを示す
type RequiredMyInterface = Required<FirstProperty> | Required<SecondProperty>;
そして、Partial
型を使って、これらのインターフェースのすべての属性をオプションにします。
その後、&
演算子を使って、2つのインターフェースを組み合わせて、MyInterface
というインターフェースを作ります。
最後に、Required
型を使って、FirstProperty
または SecondProperty
のすべての属性を必須にする型 RequiredMyInterface
を定義します。
TypeScript インターフェースで「どちらか一方」の属性を必須にするには、never
型または Partial
型と Required
型のいずれかを使用できます。
それぞれの方法にはメリットとデメリットがありますので、状況に合わせて使い分けてください。
never 型を使用する
interface MyInterface {
// どちらか一方の属性
firstProperty?: string;
secondProperty?: number;
// どちらか一方の属性が必須であることを示す
[key: string]: firstProperty extends never ? secondProperty : never;
}
function myFunction(obj: MyInterface) {
// どちらか一方の属性が必ず存在する
if (obj.firstProperty) {
console.log(obj.firstProperty);
} else {
console.log(obj.secondProperty);
}
}
const obj1: MyInterface = {
firstProperty: "Hello",
};
const obj2: MyInterface = {
secondProperty: 123,
};
myFunction(obj1); // Hello
myFunction(obj2); // 123
Partial 型と Required 型を使用する
type FirstProperty = {
firstProperty: string;
};
type SecondProperty = {
secondProperty: number;
};
type MyInterface = Partial<FirstProperty> & Partial<SecondProperty>;
// どちらか一方の属性が必須であることを示す
type RequiredMyInterface = Required<FirstProperty> | Required<SecondProperty>;
function myFunction(obj: RequiredMyInterface) {
// どちらか一方の属性が必ず存在する
if ("firstProperty" in obj) {
console.log(obj.firstProperty);
} else {
console.log(obj.secondProperty);
}
}
const obj1: RequiredMyInterface = {
firstProperty: "Hello",
};
const obj2: RequiredMyInterface = {
secondProperty: 123,
};
myFunction(obj1); // Hello
myFunction(obj2); // 123
これらのコードを実行すると、どちらか一方の属性が必ず存在すること、そしてその属性が正しく使用されていることが確認できます。
他の方法
discriminated union は、属性によって異なる型になるユニオントラブルです。この型を利用して、以下の方法で「どちらか一方」の属性を必須にできます。
interface MyInterface {
type: "first" | "second";
// type によって属性が異なる
firstProperty?: string;
secondProperty?: number;
}
function myFunction(obj: MyInterface) {
// type によって処理を分岐する
switch (obj.type) {
case "first":
console.log(obj.firstProperty);
break;
case "second":
console.log(obj.secondProperty);
break;
}
}
const obj1: MyInterface = {
type: "first",
firstProperty: "Hello",
};
const obj2: MyInterface = {
type: "second",
secondProperty: 123,
};
myFunction(obj1); // Hello
myFunction(obj2); // 123
この方法を使うことで、属性によって異なる処理を行うことができます。
型ガードを使用する
interface MyInterface {
firstProperty?: string;
secondProperty?: number;
}
function isFirs
typescript