here is what I want to do: Suppose I have an object like this:
interface X {
a: number;
b: number;
с: string;
d: number[];
}
And I want to delete ALL fields of certain type:
type DeleteFields <X, number> = ... = {c: string, d:number[]}
The best I've got is like that:
type DeleteFields <T , D> = {
[P in keyof T]: T[P] extends D ? "" : T[P];
}
type XNumbersNoNum = DeleteFields <X, number>; // { a: ""; b: ""; с: string; d: number[]; }
How can I achieve that behaviour? I tried to play with Omit and etc but didn't get anything better
We will need to use mapped types as you already do, however, we will need to use key remapping to remove the unwanted properties. key remapping
is a really useful feature that allows not only removing properties but also modifying the keys based on condition:
type Getters<Type> = {
[Property in keyof Type as `get${Capitalize<string & Property>}`]: () => Type[Property]
};
interface Person {
name: string;
age: number;
location: string;
}
// type LazyPerson = {
// getName: () => string;
// getAge: () => number;
// getLocation: () => string;
// }
type LazyPerson = Getters<Person>;
To remove the properties we will check whether the type of the property extends the type that we want to omit. If the condition is true we will use never
as a key, otherwise the key itself without modifying it. By changing the key to never
we actually remove the property, since never
is empty set, which can't be used as a key:
type DeleteFields<T, U> = {
[K in keyof T as T[K] extends U ? never : K]: T[K];
};
Testing:
type DeleteFields<T, U> = {
[K in keyof T as T[K] extends U ? never : K]: T[K];
};
// type Result = {
// с: string;
// d: number[];
// }
type Result = DeleteFields<X, number>