1

I have a interface consisting of an object with a set of properties:

interface Foo {
  prop1: string,
  prop2: number,
  prop3?: boolean,
  prop4?: object
}

Is there a way to construct a new type Bar that only contains the optional properties of Foo, but with each property being required like:

inteface Bar {
  prop3: boolean,
  prop4: object
}

Thanks.

Julian Lachniet
  • 223
  • 4
  • 25

1 Answers1

2

Certainly. First make note of the built in typescript helper types Pick and Required. Then you can build another helper type that will extract the optional keys of a type T:

type OptionalKeysOf<T> = {
    [K in keyof T]: {} extends Pick<T, K> ? K : never;
}[keyof T];

Combine all of those:

type OnlyOptionalKeysToRequired<T> = Required<Pick<T, OptionalKeysOf<T>>>;

Then, when you use it:

type Bar = OnlyOptionalKeysToRequired<Foo>;

// Hovering that reveals:
// type Bar = {
//     prop3: boolean;
//     prop4: object;
// }

Playground Link

CRice
  • 29,968
  • 4
  • 57
  • 70
  • 2
    Note: your definition of `OptionalKeysOf` doesn't really find optional properties; just ones that accept `undefined`. So `{prop1: unknown}` would show up as `prop1` being an "optional" key. You can use weak types to distinguish optional properties from ones that accept `undefined`, as shown [here](https://stackoverflow.com/a/52991061/2887218). – jcalz Sep 02 '21 at 18:55
  • 1
    Thanks @jcalz. I edited the answer to use your improved method. I was also wondering how to get it working with the new `--exactOptionalPropertyTypes` flag, but your method even seems to handle that beautifully. Thanks again! – CRice Sep 02 '21 at 19:33