3

There is the Utility type NonNullable which will remove undefined and null values from a union type. But I was wondering if there was a way to remove optional fields from a type.

Basically if I have a type like this:

type MyType = {
  thingOne: number,
  thingTwo?: number
};

I want to be able to create a type out of the required fields only

type MyRequireds = NonOptional<MyType>;
// which is a type only containing "thingOne"

Is there some utility class that would satisfy the made up "NonOptional" utility class?

Jake
  • 402
  • 1
  • 4
  • 12

2 Answers2

3

A tricky solution:

type RequiredKeys<T> = {
  [K in keyof T]: ({} extends { [P in K]: T[K] } ? never : K)
}[keyof T];

type NonOptional<T> = Pick<T, RequiredKeys<T>>;

type MyType = {
  thingOne: number,
  thingTwo?: number
};

type MyRequireds = NonOptional<MyType>;

Playground

The trick is that {} extends {thingTwo?: number} but doesn't extend {thingOne: number}. I originally found this solution here.

Valeriy Katkov
  • 33,616
  • 20
  • 100
  • 123
  • Can you expand this to include nested types? https://stackoverflow.com/questions/71501126/typescript-exclude-optional-fields-from-type-deep – lonewarrior556 Mar 16 '22 at 16:49
1

You can compress this into one type using the bellow.

type OmitOptional<T> = { 
  [P in keyof Required<T> as Pick<T, P> extends Required<Pick<T, P>> ? P : never]: T[P] 
}

Playground

For nested types @lonewarrior556

export type OmitOptionalNested<T> = { [P in keyof Required<T> as Pick<T, P> extends Required<Pick<T, P>> ? P : never]: 
        T[P] extends (infer U)[] ? OmitOptionalNested<U>[] :
        T[P] extends object ? OmitOptionalNested<T[P]> :
        T[P] 
}

Playgound

mullin
  • 133
  • 1
  • 6
  • Can you expand this to include nested types? https://stackoverflow.com/questions/71501126/typescript-exclude-optional-fields-from-type-deep – lonewarrior556 Mar 16 '22 at 16:50