TypeScript Non-Nullable Union Helper
In TypeScript, it's common to work with types that can be either a specific type or null/undefined. This can sometimes lead to unnecessary checks and can make type definitions more verbose. This challenge asks you to create a utility type that simplifies working with types that are guaranteed to be non-nullable.
Problem Description
Your task is to implement a TypeScript utility type called NonNullableUnion<T>. This utility type should take a union type T as input and return a new union type where all occurrences of null and undefined have been removed.
Key Requirements:
- Remove
null: Ifnullis part of the input unionT, it should not be present in the output type. - Remove
undefined: Ifundefinedis part of the input unionT, it should not be present in the output type. - Preserve other types: All other types within the union
Tshould be preserved in the resulting type. - Handle primitive types: The utility should correctly handle primitive types, objects, and other valid TypeScript types within the union.
- Handle existing
NonNullable: Be mindful that TypeScript already has aNonNullable<T>utility type. YourNonNullableUnion<T>should effectively apply the concept of non-nullability to each member of a union type, not just the union as a whole in a single step.
Expected Behavior:
NonNullableUnion<string | number | null>should resolve tostring | number.NonNullableUnion<string | undefined>should resolve tostring.NonNullableUnion<string | null | undefined>should resolve tostring.NonNullableUnion<{ a: number } | null>should resolve to{ a: number }.NonNullableUnion<string | null | { b: string } | undefined>should resolve tostring | { b: string }.NonNullableUnion<string>should resolve tostring.
Examples
Example 1:
type InputType1 = string | number | null;
type OutputType1 = NonNullableUnion<InputType1>;
// Expected OutputType1: string | number
Explanation: The null is removed from the union.
Example 2:
type InputType2 = { name: string } | undefined | boolean | null;
type OutputType2 = NonNullableUnion<InputType2>;
// Expected OutputType2: { name: string } | boolean
Explanation: Both undefined and null are removed, preserving the object type and the boolean type.
Example 3:
type InputType3 = number | undefined;
type OutputType3 = NonNullableUnion<InputType3>;
// Expected OutputType3: number
Explanation: Only undefined is present, and it is removed.
Constraints
- The solution must be a single TypeScript utility type definition.
- The utility type should be named
NonNullableUnion<T>. - No external libraries or packages are allowed.
- The solution should be efficient and not rely on excessively complex or recursive type manipulations if a simpler approach exists.
Notes
Consider how you can iterate over the members of a union type and apply a transformation to each member individually. TypeScript's conditional types and distributive conditional types will be key here. Think about how to check if a type is null or undefined and how to exclude it from a union.