Reputation: 16334
I have the following type in typescript:
type Foo = {
x: {};
y: {bar: string};
z: {};
};
How can I drop all the empty properties (i.e. x
and z
) so that the resulting type will look like this?
type Result = {
y: {bar: string};
}
Upvotes: 3
Views: 674
Reputation: 328107
With just your one example it's not clear which types other than literally {}
you'd be okay with dropping: for example, do you need to keep or drop the object
type? What about the unknown
type? I'm not going to worry about this too much; just know that you should probably run through a suite of possible edge cases and figure out if the behavior of any type you come up with is acceptable.
Anyway, one possible implementation that doesn't rely on importing external libraries is:
type DropEmpty<T> =
{ [K in keyof T as keyof T[K] extends never ? never : K]: T[K] };
This is using key remapping in mapped types to suppress any properties matching a certain criterion, by remapping the key in question to never
.
You can verify that this behaves as desired for your example:
type Result = DropEmpty<Foo>
/*type Result = {
y: {
bar: string;
};
} */
Upvotes: 1
Reputation: 16334
I found a solution, but it feels a bit verbose:
import type {ConditionalExcept} from 'type-fest';
type DropEmpty<T> = Pick<
T,
keyof ConditionalExcept<
{
[Property in keyof T]: keyof T[Property];
},
never
>
>;
This produces the desired result:
type Foo = {
x: {};
y: {bar: string};
z: {};
};
type Result = DropEmpty<Foo>;
Live example on codesandbox: https://codesandbox.io/s/drop-empty-properties-eu0l8
Upvotes: 0