An Alternative to the Omit Utility Type
TypeScript provides sevral utility types. We can efficiently construct new types with them. Omit<Type, Keys>
is one of them to remove specific properties from object types.
The basic usage is like this.
type NewType = Omit<OriginalType, 'propertyToRemove'>;
Pitfall
There is an pitfall of the use of Omit<Type, Keys>
. Suppose you want to remove the prop1
property from the Props
interface bellow.
interface Props {
prop1: string;
prop2: number;
prop3: boolean;
[key: string]: any;
}
You might think that Omit<Type, Keys>
can achieve that like this.
type PropsWithoutProp1 = Omit<Props, "prop1">;
However, the PropsWithoutProp1
type is interpreted as following...
type PropsWithoutProp1 = {
[x: string]: any;
[x: number]: any;
};
The prop2
and the prop3
properties are gone! This is not what we intended to do!
Let's dive into Omit<Type, Keys>
itself.
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Exclude<keyof Props, "prop1">
points to string | number
because the Prop
type has an string
index sigunature, for more details. Thus the string
overlaps "prop2" | "prop3"
.
Solution
This is one of the solutions to preserve the prop2
and the prop3
properties by re-mapping keys.
type PropsWithoutProp1 = {
[K in keyof Props as K extends "prop1" ? never : K]: Props[K];
};
The resulting type is what we expected!
type PropsWithoutProp1 = {
[x: string]: any;
prop2: number;
prop3: boolean;
};
The K in keyof Props
part iterates over "prop1" | "prop2" | "prop3" | string
, and the as K extends "prop1" ? never : K
part creates the resulting keys removing the prop1
by setting the never
in the true branch of the conditional type.