Class field initialization order different between target ES2021 and ES2022

Abierto
#52,331 8 comentarios 13 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Estancado
Stack tecnológico
javascript, typescript
Área
compilers

Línea de trabajo

Comienza con el TypeScript Playground enlazado y compara las salidas de ES2021 y ES2022 para la clase que usa una propiedad de parámetro en su inicializador de campo. Se considera terminado determinar el comportamiento o diagnóstico previsto para esta discrepancia semántica y cubrir el ejemplo reproducido con una prueba de regresión.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Experience Enhancement Help Wanted Suggestion

Bug Report

🔎 Search Terms

ES2022 class field initialization order

🕗 Version & Regression Information
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about _________
⏯ Playground Link

Playground link with relevant code

💻 Code
interface Param {
  a: number;
}

class Test {
  // constructor that sets a field
  constructor(private param: Param){
  }

  // use that field to set another field
  a = this.param.a;
}

const t = new Test({a: 10});
console.log(t.a);
🙁 Actual behavior

If the compiler is set to target "ES2021" then the output will be:

"use strict";
class Test {
    constructor(param) {
        this.param = param;
        this.a = this.param.a;
    }
}
const t = new Test({ a: 10 });
console.log(t.a);

If the target is set to "ES2022" then the output will be:

"use strict";
class Test {
    param;
    constructor(param) {
        this.param = param;
    }
    a = this.param.a;
}
const t = new Test({ a: 10 });
console.log(t.a);

These look logically the same, just utilizing the field syntax in Javascript, but in Javascript fields are initialized BEFORE the constructor is run.

So that means that ES2021 will work, setting the param field on Test and then use it to set the a field, but with ES2022 it will attempt to set a first, using the param field which has not been initialized yet, thus throwing an error at runtime.

There is no warning or error that this will happen, and I could not find any kind of compiler flag to enable such an error. Even "strictPropertyInitialization" didn't catch this like I thought it might.

🙂 Expected behavior

In order to maintain Javascript semantics, I believe that Typescript should not allow field initializers to access these automatic field setting constructor parameters. Typescript should not allow you to do something that will simply not work.

Alternatively, the compiler could be changed to insert the initializer at the end of the constructor. This would maintain existing Typescript behavior at the expense of being different from Javascript.

Lenguaje dominante
Go
Estrellas
111k
Forks
14.4k
Merge medio
1 d 15 h
PR fusionados (30 d)
106

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de microsoft/TypeScript

Todos los issues de microsoft/TypeScript

Issues similares

Más issues de Go

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.