microsoft / microsoft/TypeScript
Inherited typing for class property initializers
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Go
- Sterne
- 111k
- Forks
- 14.4k
- Ø Merge
- 1 T. 19 Std.
- Gemergte PRs (30 T.)
- 117
Beschreibung
Problem
Initializing a class member with things like { }, null, undefined, or [] has unexpected behavior.
class Base {
favorites = ["red", "blue"];
}
class Derived extends Base {
favorites = [];
constructor() {
this.favorites.push('green'); // Can't push string onto never[], wat?
}
}
interface Settings {
size?: number;
color?: string;
}
class Base {
settings: Settings = { size: 42 };
}
class Derived extends Base {
settings = { };
constructor() {
if (big) this.settings = { siz: 100 }; // no error, wat?
}
}
Solution
New rule: When a class property is initialized with exactly null, undefined, { }, or [], the type of the property is taken from the same property of the inherited type (if one exists), rather than the type of the initializer.
The inherited type is B & I1 & I2 & ... where B is the base class and I1, I2, ... are the implemented interfaces of the class.
Examples
interface Positionable {
position: string | null;
}
class MyPos implements Positionable {
position = null;
setPos(x: string) {
this.position = x;
}
getPos() {
return this.position.subtr(3); // error detected
}
}
class Base {
items = ['one'];
}
class Derived extends Base {
items = []; // no longer an implicit any
}
var x = new Derived();
x.items.push(10); // Error as expected
Bad Ideas We Thought Were good

Contextual typing plays poorly with other behavior such as unit type positions. Consider
enum E { A, B, C }
class Base {
thing = E.A;
}
class Derived extends Base {
thing = E.B;
change() {
this.thing = E.C; // Error! wat
}
}
This turns into a big problem because the E.B expression is contextually typed by the unit-like type E.A | E.B | E.C and so acquires the specific type E.B rather than the intended type E! Daniel found this break in Azure.
/cc conspirators @DanielRosenwasser @sandersn
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Das Issue nennt keine Dateien, Tests oder Einstiegspunkte. Beginne damit, die Logik zur Typinferenz und Typprüfung von Klasseneigenschaften in TypeScript zu lokalisieren, und verwende dann die Beispiele zu Base/Derived und implements als Regressionstests. Als erledigt gilt die Aufgabe, wenn null, undefined, {} und [] den passenden Eigenschaftstyp erben, ohne das hier beschriebene Problem der kontextuellen Typisierung von enum einzuführen.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- typescript
- Bereich
- compilers
- Issue-Typ
- Feature
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Aktivitätsstatus
- Ruhig
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 38/100