Conditional Type Extensions in TypeScript
Conditional types in TypeScript allow you to create types that depend on a condition. This challenge focuses on extending existing types conditionally, enabling you to dynamically add or modify properties based on a boolean condition. This is incredibly useful for creating flexible and reusable type definitions, particularly when dealing with optional features or variations in data structures.
Problem Description
You are tasked with creating a utility type called ConditionalExtend<T, U, Condition> that conditionally extends type T with the properties of type U based on the truthiness of Condition. Condition should be a type that resolves to a boolean. If Condition is truthy, the resulting type should be the intersection of T and U. If Condition is falsy, the resulting type should be T.
Key Requirements:
- The
ConditionalExtendtype must accept three generic type arguments:T(the base type),U(the type to extend with), andCondition(the boolean condition). - The
Conditiontype must be evaluated to a boolean. This means it should be a type that can be narrowed totrueorfalse. - If
Conditionevaluates totrue, the resulting type should beT & U. - If
Conditionevaluates tofalse, the resulting type should beT. - The type must be valid TypeScript and compile without errors.
Expected Behavior:
The type should correctly extend T with U only when Condition is truthy. It should not introduce any unexpected types or errors.
Edge Cases to Consider:
Conditionbeing a type that resolves to a literaltrueorfalse.TorUbeing empty objects ({}).TandUhaving overlapping properties. The intersection should handle this correctly (properties from both types are present).Conditionbeing a complex type that requires type inference.
Examples
Example 1:
type Base = {
name: string;
age: number;
};
type Extension = {
city: string;
};
type Condition = true;
type Result1 = ConditionalExtend<Base, Extension, Condition>;
// Result1: {
// name: string;
// age: number;
// city: string;
// }
Example 2:
type Base = {
name: string;
age: number;
};
type Extension = {
city: string;
};
type Condition = false;
type Result2 = ConditionalExtend<Base, Extension, Condition>;
// Result2: {
// name: string;
// age: number;
// }
Example 3:
type Base = {
name: string;
age: number;
};
type Extension = {
city: string;
age: string; // Overlapping property
};
type Condition = true;
type Result3 = ConditionalExtend<Base, Extension, Condition>;
// Result3: {
// name: string;
// age: number;
// city: string;
// }
Constraints
- The solution must be a valid TypeScript type definition.
- The solution should be concise and readable.
- The solution should handle all the edge cases mentioned above.
- No runtime code is required; this is purely a type-level challenge.
Notes
Consider using the conditional type syntax (T extends U ? ... : ...) to implement this. Think about how to ensure that the Condition type is properly evaluated to a boolean value within the conditional type. The key is to leverage TypeScript's type system to perform this conditional extension at compile time.