m.s.
m.s.

Reputation: 16334

exclude properties with empty object type from type in TypeScript

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

Answers (2)

jcalz
jcalz

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;
    };
} */

Playground link to code

Upvotes: 1

m.s.
m.s.

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

Related Questions