In TypeScript, how can I reference the value being extended for a generic on a type? For example, if I have type MyType<T extends string> = Record<T, number>; , how could I reference the “string” being extended for the generic T?
While you can’t directly reference the exact value being extended within a generic type declaration, here are several effective approaches to achieve similar goals:
1. Conditional Types:
- Employ conditional types to constrain type behavior based on the generic’s relationship to the extended type.
type MyType<T extends string> = {
[P in T]: number;
isString: T extends string ? true : false; // Leverage conditional type
};
const myObject: MyType<"name" | "age"> = {
name: 42,
age: 30,
isString: true, // Correctly infers as true
};
2. Type Inference and Utility Types:
- Utilize type inference and built-in utility types to derive information about the generic.
type InstanceType<T> = T extends infer U ? U : never;
type Stringified<T extends string> = InstanceType<T>; // Extract string type
const myString: Stringified<MyType<"name" | "age">> = "name"; // Correctly infers as string
3. Type Parameters and Constraints:
- Define additional type parameters with constraints for more control and flexibility.
type MyType2<T extends string, U extends T = T> = Record<U, number>;
const myObject2: MyType2<"name" | "age"> = {
name: 42, // T is inferred as "name" | "age"
age: 30,
};
Remember:
- These techniques offer ways to work with generic type relationships without direct value access.
- Choose the approach that best aligns with your specific use case and constraints.
- For more complex scenarios, consider combining these techniques or exploring advanced TypeScript features.
None of those solutions get the type of the generic being extended. Are there no real solutions?
You’re absolutely right. Unfortunately, TypeScript currently lacks a mechanism to directly retrieve the exact type value being used for extension within a generic type definition. The methods presented earlier provide alternative approaches to achieve similar goals and leverage type information, but they don’t capture the precise extended value.
There are ongoing discussions and proposals for introducing “higher-kinded types” in future TypeScript versions, which could potentially enable direct access to the extended type value. However, this feature is not yet available, and it’s unclear when or if it will be implemented.
For now, the best course of action is to adopt one of the previously mentioned strategies that best suits your specific requirements and consider refactoring your code if necessary to avoid relying on directly accessing the extended type value.