typescripttypescript-typingstypescript4.0

typescript exclude optional fields from type (deep)


This is an expansion of this questions: typescript exclude optional fields from type

If I have a type like this:

type MyType = {
  thingOne: { id: string; name?: string };
  thingTwo?: { id: string; name?: string };
};

I want to be able to create a type that only has the required fields in the object, aswell as anything nested inside of it.

ie.

type MyRequireds = NonOptional<MyType>;
/*
{
  thingOne: { id: string };
};
*/

is it possible?

TSPlayground link with shallow NonOptional TypeScripPlayground


Solution

  • With this recursive type:

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

    If T is a primitive, we don't need to do anything. However if it is an object we have to go through each key and get only the ones that can't be optional (credit to @jcalz) and then recursively gets only required keys of T[K].

    Note that functions need a little special handling and checking for undefined is not exhaustive or the best way to check for optional properties but it does work for your example.

    Playground