microsoft / microsoft/TypeScript
JSDoc tag for getting around "Object literals are open-ended"
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Go
- Estrellas
- 111k
- Forks
- 14.3k
- Merge medio
- 2 d 4 h
- PR fusionados (30 d)
- 132
Descripción
🔍 Search Terms
label:"Domain: JSDoc" open-ended
label:"Domain: JSDoc" literal
label:checkJs open-ended
label:checkJs literal
✅ Viability Checklist
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
⭐ Suggestion
According to the documentation, TypeScript treats inferred object literals in checked .js files as open-ended by default. This is good and makes sense, but is annoying for the times when it isn't the desired functionality.
I'd like for a new tag to be introduced. I'll be using @closed as an example, but I'm fine with whatever wording, really. The new tag would be used on an object definition in order to opt out of this open-ended behavior for that specific object literal declaration.
Ideally, this would be done recursively through the object's definition (i.e. I shouldn't have to define @closed for each sub-object), but I understand if that's too broad-reaching. I'd be fine with having that limitation.
This is obviously very similar to Exact Types (#12936), but it concerns general exact object types and structural compatibility, whereas this request is limited to a JSDoc opt-in for inferred object literals in checked JavaScript. I therefore believe this warrants its own feature request.
📃 Motivating Example
I use JSDoc quite extensively in my hobby work. I often run into issues like this:
class CustomFooBarElement extends HTMLElement {
_elements = {
/** @type {HTMLSpanElement|null} */
foo: null,
};
constructor() {
super();
this._elements.bar = document.createElement("span");
// ^ currently doesn't report an error
}
}
Now, you can easily work around this by adding a full object typing to the _elements object:
class CustomFooBarElement extends HTMLElement {
/** @type {{foo: HTMLSpanElement|null}} */
_elements = {
foo: null,
};
which would cause the .bar access to fail. However, maintaining such a declaration can quickly grow cumbersome when the _elements object grows in size and complexity:
class CustomFooBarElement extends HTMLElement {
/**
* @type {{
* foo: HTMLSpanElement | null,
* buttons: {
* primary: {
* a: HTMLButtonElement | null,
* b: HTMLButtonElement | null,
* },
* },
* images: {
* a: HTMLImageElement | null,
* b: HTMLImageElement | null,
* },
* }}
*/
_elements = {
foo: null,
buttons: {
primary: {
a: null,
b: null,
},
},
images: {
a: null,
b: null,
},
};
A silly example, but I think you get the point. Not to mention the fact that you've completely decoupled the type definition from the definition of the variable itself.
Now, if I instead could do something like this:
class CustomFooBarElement extends HTMLElement {
/** @closed */
_elements = {
/** @type {HTMLSpanElement|null} */
foo: null,
buttons: {
primary: {
/** @type {HTMLButtonElement|null} */
a: null,
/** @type {HTMLButtonElement|null} */
b: null,
},
},
images: {
/** @type {HTMLImageElement|null} */
a: null,
/** @type {HTMLImageElement|null} */
b: null,
},
};
It's much easier to handle, and would lead to the desired result:
this._elements.bar = document.createElement("span");
// ^^^ error: Property 'bar' does not exist
this._elements.buttons.primary.c = document.createElement("button");
// ^ error: Property 'c' does not exist
💻 Use Cases
- What do you want to use this for?
Typing fixed-shape objects. See the examples above.
- What shortcomings exist with current approaches?
The object-declaration-level @type requires essentially repeating the entire structure of the object. It also decouples the type of the actual leaf property from its definition.
- What workarounds are you using in the meantime?
I started with the object-declaration-level @type, but at this point I just use the leaf-level @type and hope I don't run into any spelling mistakes or such.
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 la sección del handbook “Object literals are open-ended” y el Exact Types issue enlazado (#12936), y luego investiga el comportamiento de JSDoc en checked JavaScript descrito en los ejemplos. El trabajo estará terminado cuando exista una opción documentada de opt-in mediante JSDoc para literales de objeto inferidos con forma fija, incluido el alcance acordado para los objetos anidados, y se rechacen las asignaciones de propiedades adicionales mostradas.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- javascript, typescript
- Área
- compilers
- Tipo de issue
- Nueva funcionalidad
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Estado de actividad
- Tranquilo
- Claridad
- Bastante claro
- Aptitud para principiantes
- 45/100