⌨️
TypescriptでUnionにOmitして共通ではないプロパティが消えてこまったら
多分Pickとかでもそうなんだけど、UnionにOmitすると共通ではないプロパティは消えます。
そこで Distributive conditional typeを使って丁寧にOmitする必要がある。
消える例
type UnionType =
| {
a: true;
b: Record<string, unknown>; //これが後で消える
}
| {
a?: false;
};
type ComplexType = {
id: string;
name: string;
} & UnionType;
type TypeWithoutName = Omit<ComplexType, 'name'>;
const a1: UnionType = {} as any;
const a2: ComplexType = {} as any;
const a3: TypeWithoutName = {} as any;
if (a1.a) {
console.log(a1.b);
}
if (a2.a) {
console.log(a2.b);
}
if (a3.a) {
console.log(a3.b); // TS can't find b because of Omit ???
}
消えない例 from stack overflow
type DistributiveOmit<T, K extends keyof any> = T extends any
? Omit<T, K>
: never;
type TypeWithoutName = DistributiveOmit<ComplexType, 'name'>;
const a4: TypeWithoutName = {} as any;
if (a4.a) {
console.log(a4.b); // Okay !
}
イメージとしては、 Omit<A | B | C, Key>
を Omit<A, Key> | Omit<B, Key> | Omit<C, Key>
とする必要があるということ。
集合の演算として交換法則が成り立たないってことなんだなこれ。
Discussion