Búsqueda de sitios web

angular - ¿Cómo funciona la conversión de clases en Typescript?


Tengo una pregunta sobre Casting en Typescript.

Tuve el caso de uso en el que convertí un objeto a un tipo específico de una clase que tenía un método. Cuando después quise llamar a este método, estaba indefinido, compara el fragmento a continuación:

export class Test {
  property1: any;
  property2: any;

  constructor(){}

  sayHello(): string {
    return 'hello';
  }
}


testData = {
    property1: '',
    property2: 2
  } as Test;

testData.sayHello(); <-- undefined

También preparé un ejemplo funcional o más bien no funcional en una aplicación de Angular en Stackblitz: https://stackblitz.com/edit/angular-y3s9r4

¿Alguien puede explicar este comportamiento? ¿Y cómo es posible también heredar métodos?

Respuesta #1

En TypeScript esto se llama una aserción de tipo, no una conversión. La razón de la terminología diferente es exactamente que esto se comporta de manera distinta a otros lenguajes, es decir, no hay comportamiento en tiempo de ejecución. Las aserciones de tipo no convierten valores ni realizan ninguna verificación en tiempo de ejecución, solo le indican al compilador que tú, como desarrollador, sabes que un cierto valor será de un tipo determinado. Cómo tienes este conocimiento no es asunto del compilador.

Entonces este código :

testData = {
    property1: '',
    property2: 2
  } as Test;

Simplemente le dice al compilador que el literal de objeto es del tipo Test. El literal de objeto tiene los mismos campos que tu clase, pero no tendrá ninguno de los métodos (ya que nadie los puso allí).

Para crear una instancia de la clase debes usar el operador new con el constructor de la clase. Si deseas pasar los datos, puedes tener un constructor que acepte los datos y los asignará a la instancia actual:

export class Test {
    property1: any;
    property2: any;

    constructor(data: Partial<Test>) {
        Object.assign(this, data);
    }

    sayHello(): string {
        return 'hello';
    }
}


let testData = new Test({
    property1: '',
    property2: 2
});

testData.sayHello();  //ok 

Respuesta #2

Hay una diferencia entre objetos simples e instancias de clases. Déjame explicarlo en Javascript.

Cuando escribes esto:

const x = { id: 0 };

se traduce a esto :

const x = { id: 0 };

Pero cuando escribes esto

class Test { 
  id = 0;

  getId() { 
   return this.id; 
 } 
}
const x = new Test();

Se traduce así:

function Test() {
  this.id = 0;

  this.getId = () => this.id;
}
const x = new Test();

Como puedes ver, en el primer caso, no hay función. En el segundo caso, sí la hay.

Cuando escribes esto en Typescript:

const x: Test = {id: 1};

Esto es solo una conveniencia para el desarrollador, porque las variables no tienen tipo en Javascript. Aquí es donde entra en juego tu linter y te dice que hay un error.

Artículos relacionados