TypeScript-Version: 2.1.1
Code
type A = { a: string; }
type B = { b: string; }
type AorB = A | B;
declare const AorB: AorB;
if (AorB.a) {
// use AorB.a
}
Erwartetes Verhalten:
Der Code wird fehlerfrei kompiliert. Obwohl a
nicht (notwendigerweise) für alle Mitglieder der Gewerkschaft existiert, sollte die Tatsache, dass es für einige existiert, es mir ermöglichen, nach .a
und es zu verwenden, wenn es vorhanden ist.
Tatsächliches Verhalten:
Typoskript beschwert sich: "Eigenschaft a existiert nicht für Typ AorB ... Eigenschaft a existiert nicht für Typ B."
Der Arzt sagt:
Damit derselbe Code funktioniert, müssen Sie eine Typzusicherung verwenden:
let pet = getSmallPet();
if ((<Fish>pet).swim) {
(<Fish>pet).swim();
}
else {
(<Bird>pet).fly();
}
http://www.typescriptlang.org/docs/handbook/advanced-types.html
Dann in Ihrer Probe:
if ((<A>AorB).a) {
// use AorB.a
}
Das Problem hierbei ist, dass B
keine a
-Eigenschaft deklariert und zur Laufzeit möglicherweise eine a
-Eigenschaft eines beliebigen Typs aufweist (da Sie eine zuweisen können Objekt mit einem beliebigen Satz von Eigenschaften zu einem B
, solange es eine b
-Eigenschaft vom Typ string hat). Sie können dafür sorgen, dass eine a: undefined
-Eigenschaft explizit in B
deklariert wird (wodurch sichergestellt wird, dass B
keine zufällige a
-Eigenschaft hat):
type A = { a: string; }
type B = { b: string; a: undefined }
type AorB = A | B;
declare const AorB: AorB;
if (AorB.a) {
// Ok
}
Macht perfekt Sinn. Gehirnfurz.
Wenn Sie a: undefined
für Typ B definieren, müssen Sie es beim Erstellen / Übergeben einer Variablen auf undefined
.
Um dies zu umgehen, können Sie a
als a?: undefined
deklarieren, und Typoskript freut sich, wenn Sie es weglassen.
Wenn ich die Kommentare richtig verstehe, sollte dies funktionieren (aber wirft; auf dem Spielplatz getestet): Ist das ein Fehler oder nicht? 🤔
type LinkProps = {
to: string;
onClick?: undefined;
// Link specific props:
target: string;
}
type ButtonProps = {
to?: undefined;
onClick: Function;
// Button specific props:
disabled: boolean;
}
type ActionProps = LinkProps | ButtonProps;
const Action = (props: ActionProps) =>
props.to ?
'Link with target: ' + props.target // Error not on ButtonProps
:
'Button with disabled: ' + props.disabled; // Error: not on LinkProps
Action({
to: 'dssd',
target: '_blank'
});
Ich verstehe das überhaupt nicht. Ist if ((<A>AorB).a)
dasselbe wie if (A.a)
weil Sie es zurückzwingen, A
einzugeben?
Wenn Sie
a: undefined
für Typ B definieren, müssen Sie es beim Erstellen / Übergeben einer Variablen aufundefined
.
Um dies zu umgehen, können Siea
alsa?: undefined
deklarieren, und Typoskript freut sich, wenn Sie es weglassen.
Vielleicht ist es besser a?: never
, jetzt können Sie nicht versehentlich undefined
zuweisen
Was ist, wenn Sie nicht jedem Gewerkschaftsmitglied einen Namen geben? (Ich kann keine Typzusicherung wie oben ohne einen Namen für den bestätigten Typ vornehmen, oder?)
type u = "str" | {prop:"val"};
function f(arg:u){return arg.prop} // TypeScript: Property 'prop' does not exist on type 'u'
Irgendeine Lösung?
Ich finde eine Lösung im Buch:
interface A { x: number;}
interface B { y: string;}
function doStuff ( q: A | B ) {
if ( 'x' in q) {
// if type A...
}
else {
// if type B...
}
}
Auszug aus: Basarat Ali Syed. "TypeScript Deep Dive." Apple Bücher.
Eine Eigenschaft für ein Objekt, die als Typschutz verwendet werden kann, und das TypeScript kann erkennen, welchen Typ Sie verwendet haben.
type ColorItemType = {
colorId: number,
colorName: string,
}
type NumItemType = {
numId: number,
numName: string
}
type ResType = {
itemId: number,
// 0 color 1 num
type: number,
itemInfo: {
colorList: Array<ColorItemType>
numList: Array<NumItemType>
}
}
const request = () => {
return [{
itemId: 1,
type: 0,
itemInfo: {
colorList: [{
colorId: 1,
colorName: 'blue'
}],
numList: []
}
}];
};
const dataSource: Array<ResType> = request();
const formatData = dataSource.map(dataItem => {
const list: Array<ColorItemType | NumItemType> = dataItem.type === 1 ? dataItem.itemInfo.numList : dataItem.itemInfo.colorList;
return list.map(listItem => {
return {
// An error will be reported here
value: listItem.numId || listItem.colorId,
label: listItem.numName || listItem.colorName
};
});
});
Das Problem hierbei ist, dass
B
keinea
-Eigenschaft deklariert und zur Laufzeit möglicherweise einea
-Eigenschaft eines beliebigen Typs aufweist (da Sie eine zuweisen können Objekt mit einem beliebigen Satz von Eigenschaften zu einemB
, solange es eineb
-Eigenschaft vom Typ string hat). Sie können dafür sorgen, dass einea: undefined
-Eigenschaft explizit inB
deklariert wird (wodurch sichergestellt wird, dassB
keine zufälligea
-Eigenschaft hat):type A = { a: string; } type B = { b: string; a: undefined } type AorB = A | B; declare const AorB: AorB; if (AorB.a) { // Ok }
Funktioniert bei mir nicht 07.10.2020
Und ich denke, dass dieses Verhalten von TS nicht gut ist, weil es einem Entwickler nicht viel hilft ...
Hilfreichster Kommentar
Ich finde eine Lösung im Buch:
Auszug aus: Basarat Ali Syed. "TypeScript Deep Dive." Apple Bücher.
Eine Eigenschaft für ein Objekt, die als Typschutz verwendet werden kann, und das TypeScript kann erkennen, welchen Typ Sie verwendet haben.