TypeScriptで交差型のプロパティを上書きする方法は?
例えば、私がこれらの型を持っているとしましょう:
type BaseAnimal = {
species: string
owner: boolean
}
type Cat = BaseAnimal & {
species: 'cat'
hasTail: boolean
}
type Dog = BaseAnimal & {
species: 'dog'
likesWalks: boolean
}
type Animal = Cat | Dog
そして、AnimalParams という型を作りたいです。これは Animal と同じですが、owner プロパティだけは文字列です。
以下のどちらもできません。
// This seems to keep the owner property from Animal instead of overwriting
// So it raises an error if I try to specify owner as a string
type AnimalParams = Animal & {
owner: string
}
// This strips away properties unique to Cat or Dog
// So it raises an error if I try to specify hasTail or likesWalks
type AnimalParams = Omit<Animal, 'owner'> & {
owner: string
}
今のところ、私が思いつく唯一の回避策は以下のようにすることですが、これは不必要に繰り返しが多いように思えます。もっとすっきりと簡潔な方法はあるでしょうか?
type CatParams = Omit<Cat, 'owner'> & {
owner: string
}
type DogParams = Omit<Dog, 'owner'> & {
owner: string
}
type AnimalParams = CatParams | DogParams
ユーティリティ型に関するいくつかのSOスレッド(例えば、TypeScriptのd.tsファイルで定義されたインターフェースのプロパティ型を上書きする方法のような、インターフェース向けのもの)を読みましたが、必要なものは見つかりませんでした。事前にご回答いただけるとありがとうございます!
回答 #1
各型から owner プロパティを手動で省略する代わりに、分配条件型を使用できます:
type OmitOwner<T = Animal> = T extends BaseAnimal ? Omit<T, 'owner'> : never;
type AnimalParams = OmitOwner & {
owner: string
};
どれに相当しますか:
(Omit<Cat, 'owner'> & { owner: string; })
| (Omit<Dog, 'owner'> & { owner: string; })
それは、ユニオン型に対する自動的な分配によるものです
T extends U ? X : Yのインスタンス化において、型引数A | B | CをTに指定すると、(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)と解決されます
遊び場
なぜ元の試みはうまくいかないのですか?
「keyof」ユニオンは、ユニオン内の型のキーの交差を生成するので
type AnimalKeys = keyof Animal // is "species" | "owner"
そして Omit の実装は次の通りです:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
回答 #2
私はこれを使って、Reactでpropsを上書きすることに成功しています:
type Overwrite<T, NewT> = Omit<T, keyof NewT> & NewT;
export type TouchableAvatarPropTypes = Overwrite<AvatarPropTypes, {
/** Function executed when avatar is pressed. */
onPress: () => void;
/** Size of the avatar */
size: number;
}>
エクスポートのためにかなりきれいな一行コードを作ることができます。
