microsoft / microsoft/TypeScript
Suggesion: Allow recursive/self-references in `satisfies` constraint
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Go
- Estrellas
- 111k
- Forks
- 14.4k
- Merge medio
- 1 d 19 h
- PR fusionados (30 d)
- 117
Descripción
Suggestion
🔍 Search Terms
satisfies keyword, recursion, recursive, constraint, self referential
✅ Viability Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
It would only make previously rejected type assertions possible as it only widens the set of valid type restrictions.
- This wouldn't change the runtime behavior of existing JavaScript code
satisfiesonly exists during type checking and does not in generated JavaScript - This could be implemented without emitting different JS based on the types of the expressions
As above
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
As above
- This feature would agree with the rest of TypeScript's Design Goals.
The same is already possible using a constrained identity function
⭐ Suggestion
It is currently not possible to reference the type of a variable that the satisfies constraint is applied on. Enabling this functionality should not be hard, as the same behavior can be recreated using a constrained identity function, see below. This would enable more precise verification of structures by the type checker.
📃 Motivating Example
// I define a (very simplified) state machine by the following type:
type States<S extends string> = Record<S, S>;
// I can then define a map of machine names to their states records:
const myMachines1 = {
alan: {
a: "b",
b: "c",
c: "c",
},
turing: {
x: "y",
y: "x",
},
} satisfies Record<string, States<string>>;
// Problem: This is possible, though should be invalid:
const myMachines2 = {
foo: {
a: "x",
},
bar: {
x: "a",
}
} satisfies Record<string, States<string>>;
// Solution 1: Identity function with self-referential generic:
function defineMachines<T extends {
[name in keyof T]: States<keyof T[name] & string>;
}>(machines: T) {
return machines;
}
// Valid:
const myMachines3 = defineMachines({
alan: {
a: "b",
b: "c",
c: "c",
},
turing: {
x: "y",
y: "x",
},
});
// Errors:
const myMachines4 = defineMachines({
foo: {
a: "x",
},
bar: {
x: "a",
}
});
// Solution 2: The same behavior should be achievable using the new `satisfies` keyword:
const myMachines5 = {
foo: {
a: "x",
},
bar: {
x: "a",
}
} satisfies {
[name in keyof typeof myMachines5]: States<keyof typeof myMachines5[name] & string>;
};
// But errors: Block-scoped variable 'myMachines5' used before its declaration.
💻 Use Cases
As seen in the example above, this allows for a more precise control over (nested) type restrictions. It is already possible to self-reference type definitions, so why shouldn't this also be possible for variable declarations? The satisfies keyword does not modify the type itself to my knowledge.
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza con los ejemplos motivadores de satisfies y compara la autorreferencia rechazada con la solución basada en una función identidad con restricciones. Determina cómo deberían comportarse las restricciones recursivas para las declaraciones de variables y, después, valida que se acepten los mapas válidos de máquinas de estados y se rechacen las referencias cruzadas no válidas sin cambiar la salida en tiempo de ejecución.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- typescript
- Área
- compilers
- Tipo de issue
- Nueva funcionalidad
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Estado de actividad
- Estancado
- Claridad
- Bastante claro
- Aptitud para principiantes
- 30/100