Typen aus Werten
Normalerweise schreibst du zuerst einen Typ und dann Werte, die dazu passen. Manchmal ist es umgekehrt: Der Wert kommt zuerst, und der Typ soll ihm folgen. Jeder neue Held beginnt mit denselben Werten, die einmal in einem Objekt stehen:
const startattribute = { staerke: 5, geschick: 5, magie: 5 };Funktionen, die mit diesen Werten arbeiten, brauchen einen Typ dafür. Du könntest { staerke: number; geschick: number; magie: number } von Hand schreiben, müsstest ihn aber bei jeder Änderung des Objekts mitändern. TypeScript kann den Typ stattdessen aus dem Wert nehmen:
const startattribute = { staerke: 5, geschick: 5, magie: 5 };
type Attribute = typeof startattribute;
const magierAttribute: Attribute = { staerke: 2, geschick: 4, magi: 9 };main.ts(4,63): error TS2561: Object literal may only specify known properties, but 'magi' does not exist in type '{ staerke: number; geschick: number; magie: number; }'. Did you mean to write 'magie'?Attribute ist der Typ, den TypeScript für startattribute abgeleitet hat, { staerke: number; geschick: number; magie: number; }, und so schreibt ihn die Meldung auch. Die Eigenschaften sind number, nicht 5, weil sich die Eigenschaften eines Objekts ändern können. Wenn du startattribute eine Eigenschaft hinzufügst, bekommt Attribute sie auch, und TypeScript meldet jedes Objekt vom Typ Attribute, das sie noch nicht hat.
typeof kennst du aus JavaScript: typeof gold === "number". Dieses typeof arbeitet, während das Programm läuft, und gibt einen Text wie "number" oder "object" zurück. In einem Typ (nach type Attribute = oder nach einem Doppelpunkt) gehört typeof zu TypeScript: Es gibt den Typ einer Variablen zurück und verschwindet wie jeder Typ aus dem Programm. Du hast es schon in der Lektion „Daten modellieren“ verwendet: (typeof klassen)[number].
const startattribute = { staerke: 5, geschick: 5, magie: 5 };
type Attribute = typeof startattribute;
const kopie: Attribute = { ...startattribute };
console.log(typeof kopie);
console.log(kopie);Das gibt aus:
object
{ staerke: 5, geschick: 5, magie: 5 }Werte und Typen leben in zwei getrennten Welten. startattribute ist ein Wert (eine Variable), Attribute ist ein Typ, und typeof bringt den Typ eines Werts in die Welt der Typen. Du kannst startattribute selbst nicht mit Attribute annotieren, denn der Typ stammt ja von ihm.
Typische Fehler:
typeofweglassen,type Attribute = startattribute;. Die Meldung sagt dir, was du schreiben musst:main.ts(2,18): error TS2749: 'startattribute' refers to a value, but is being used as a type here. Did you mean 'typeof startattribute'?- Andersherum:
typeof Held, wobeiHeldein Typ ist, ergibt'Held' only refers to a type, but is being used as a value here.Ein Typ hat keinen Wert, also gibt es nichts, wovon mantypeofnehmen könnte. Verwende den TypHelddirekt.
So schreibst du es:
Anweisungen
- 1
Erstelle unter
startattributeden Typtype Attribute = typeof startattribute;. Verwende ihn inaddiereAttributefür beide Parameter und den Rückgabetyp statt der drei langen Typen, und annotiere damit auchkriegerBonusundmagierBonus. Das Programm gibt dasselbe aus wie vorher. - 2
Helden bekommen einen neuen Wert, Glück. Füge
glueck: 1zustartattributehinzu und führe das Programm aus.Attributehat jetzt auchglueck, und TypeScript meldet drei Stellen, die es noch nicht haben, mit Fehlern wie diesem:main.ts(6,7): error TS2741: Property 'glueck' is missing in type '{ staerke: number; geschick: number; magie: number; }' but required in type '{ staerke: number; geschick: number; magie: number; glueck: number; }'.Behebe alle drei: Gib dem Krieger einen Glücksbonus von
0und dem Magier2, und addiere inaddiereAttributeauch das Glück. Das Programm gibt aus:{ staerke: 9, geschick: 6, magie: 5, glueck: 1 } { staerke: 5, geschick: 6, magie: 10, glueck: 3 }