Reputation: 4479
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
Upvotes: 2
Views: 813
Reputation: 153
For omitting optional fields from nested objects
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]
}
Note: linters can sometimes only show one red squiggle at a time but it will break on compile saving you headaches
For the future, you can make almost any type a nested type by using the bellow template
type Basic<T> = { [P in keyof T]: T[P] }
type Nested<T> = { [P in keyof T]: // some logic to limit keys in object
T[P] extends (infer U)[] ? Nested<U>[] : // handles array
T[P] extends object ? Nested<T[P]> : // handles objects
T[P] // Same as in Basic<T>
}
Upvotes: 1
Reputation: 26324
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.
Upvotes: 1