angular - Hur fungerar klassomkastning i Typescript


Jag har en fråga angående typomvandling i Typescript.

Jag hade use-caset att jag kastade ett objekt till en specifik typ av en klass som hade en metod. När jag därefter ville kalla på denna metod var den odefinierad, jämför kodsnutten nedan:

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

  constructor(){}

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


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

testData.sayHello(); <-- undefined

Jag har också förberett ett fungerande eller snarare icke fungerande exempel i en Angular-applikation på Stackblitz: https://stackblitz.com/edit/angular-y3s9r4

Kan någon förklara detta beteende? Och hur är det också möjligt att ärva metoder?

Svar #1

I TypeScript kallas detta en typangivelse, inte en typomvandling. Anledningen till den olika terminologin är precis att detta beter sig annorlunda än i andra språk, nämligen att det inte finns något runtime-beteende. Typangivelser konverterar inte värden och utför inga runtime-kontroller, de talar bara om för kompilatorn att du, som utvecklare, vet att ett visst värde kommer att vara av en viss typ. Hur du har denna kunskap är kompilatorns angelägenhet inte.

Så den här koden :

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

Bara talar om för kompilatorn att objektliteralet är av typen Test. Objektliteralet har samma fält som din klass men det kommer inte att ha några av metoderna (eftersom ingen lade dit dem).

För att skapa en instans av klassen måste du använda new-operatorn tillsammans med klassens konstruktor. Om du vill skicka in data kan du ha en konstruktor som accepterar datan och kommer att tilldela den till den nuvarande instansen:

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 

Svar #2

Det finns en skillnad mellan vanliga objekt och klassinstanser. Låt mig förklara detta i Javascript.

När du skriver detta :

const x = { id: 0 };

det översätts till detta :

const x = { id: 0 };

Men när du skriver detta

class Test { 
  id = 0;

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

Det översätts till detta :

function Test() {
  this.id = 0;

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

Som du kan se finns det ingen funktion i det första fallet. I det andra fallet finns det en.

När du skriver detta i Typescript:

const x: Test = {id: 1};

Detta är bara en bekvämlighet för utvecklare, eftersom variabler inte är typade i Javascript. Det är här din linter kommer in och berättar för dig att det finns ett fel.

Relaterade artiklar