🔍 Search Terms
must-infer generic
immutable generic
avoid override generic
✅ Viability Checklist
⭐ Suggestion
TypeScript currently allows developers to specify generic types explicitly, which can override TypeScript’s inferred types. While this flexibility is powerful, there are cases where it is essential to prevent the user from altering the generic type, ensuring that the type inference mechanism retains full control.
I propose adding a "must-infer" modifier for generics, where the TypeScript compiler would infer the type without allowing any user overrides. The syntax could be as follows:
function test<infer X>(value: X): X {
return value;
}
This approach enforces that X is determined solely by the TypeScript compiler based on the input value, and it cannot be explicitly set by the user.
For example:
test<number>(123); // Error: X cannot be set by the user
📃 Motivating Example
This feature enhances type safety by ensuring that the generic type is always determined by TypeScript’s inference system, which is particularly useful in cases where the generic type must match the input type exactly. This prevents potential misuse or errors that could arise from explicitly overriding the inferred type.
💻 Use Cases
In my real-world scenario, I have a method that needs to capture the string representing the name of an attribute and the type of its value. To achieve this, I do the following:
class Example<Attributes extends object = object> {
private attributes = new Map<string, any>()
public attribute<Name extends string, Type>(name: Name, value: Type) {
this.attributes.set(name, value);
return this as Example<Attributes & { [K in Name]: Type }>;
}
}
const example = new Example()
.attribute("user", "John Doe")
.attribute("age", 33);
// typeof example ~= Example<{ user: string; age: number }>
However, note that I can "subvert" the type by overriding the generic:
.attribute<number | string>("age", 33)
// typeof example ~= Example<{ user: string; age: number | string }>
This is not the expected behavior. Even worse, it allows the user to manipulate my generics, while I intended to use them solely to "pass through" the input type to the output. This restricts future maintenance; if I ever want to change or remove a generic, I wouldn’t be able to do so.
In this case, the proposal would be something like:
public attribute<infer Name extends string, infer Type>(name: Name, value: Type) { ... }
From there, TypeScript itself would infer the types of Name and Type, and the user wouldn’t be able to modify them. This would allow me to maintain the freedom to change my generics without worrying about breaking changes.
My other idea was to simply use typeof, but that doesn’t work well because it expands the type too broadly. For example:
public attribute(name: string, value: any) {
this.attributes.set(name, value);
return this as Example<Attributes & { [K in typeof name]: typeof value }>;
}
// typeof example ~= Example<{ [x: string]: any }>
This doesn’t achieve the desired precision, as it leads to overly generalized types.
🔍 Search Terms
must-infer generic
immutable generic
avoid override generic
✅ Viability Checklist
⭐ Suggestion
TypeScript currently allows developers to specify generic types explicitly, which can override TypeScript’s inferred types. While this flexibility is powerful, there are cases where it is essential to prevent the user from altering the generic type, ensuring that the type inference mechanism retains full control.
I propose adding a "must-infer" modifier for generics, where the TypeScript compiler would infer the type without allowing any user overrides. The syntax could be as follows:
This approach enforces that
Xis determined solely by the TypeScript compiler based on the input value, and it cannot be explicitly set by the user.For example:
📃 Motivating Example
This feature enhances type safety by ensuring that the generic type is always determined by TypeScript’s inference system, which is particularly useful in cases where the generic type must match the input type exactly. This prevents potential misuse or errors that could arise from explicitly overriding the inferred type.
💻 Use Cases
In my real-world scenario, I have a method that needs to capture the string representing the
nameof an attribute and the type of itsvalue. To achieve this, I do the following:However, note that I can "subvert" the type by overriding the generic:
This is not the expected behavior. Even worse, it allows the user to manipulate my generics, while I intended to use them solely to "pass through" the input type to the output. This restricts future maintenance; if I ever want to change or remove a generic, I wouldn’t be able to do so.
In this case, the proposal would be something like:
From there, TypeScript itself would infer the types of
NameandType, and the user wouldn’t be able to modify them. This would allow me to maintain the freedom to change my generics without worrying about breaking changes.My other idea was to simply use
typeof, but that doesn’t work well because it expands the type too broadly. For example:This doesn’t achieve the desired precision, as it leads to overly generalized types.