Version de TypeScript: 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
}
Comportement prévisible:
Le code se compile sans erreur. Même si a
n'existe pas (nécessairement) sur tous les constituants du syndicat, le fait qu'il existe sur certains devrait me permettre de vérifier .a
et de l'utiliser s'il est présent.
Comportement réel:
Typecript se plaint: "La propriété a n'existe pas sur le type AorB ... La propriété a n'existe pas sur le type B."
Le doc dit:
Pour que le même code fonctionne, nous devons utiliser une assertion de type:
let pet = getSmallPet();
if ((<Fish>pet).swim) {
(<Fish>pet).swim();
}
else {
(<Bird>pet).fly();
}
http://www.typescriptlang.org/docs/handbook/advanced-types.html
Puis dans votre échantillon:
if ((<A>AorB).a) {
// use AorB.a
}
Le problème ici est que, comme B
ne déclare pas a
propriété a
de n'importe quel type possible (car vous pouvez attribuer un objet avec n'importe quel ensemble de propriétés à un B
tant qu'il a une propriété b
de type chaîne). Vous pouvez le faire fonctionner explicitement en déclarant une propriété a: undefined
dans B
(garantissant ainsi que B
n'aura pas a
propriété
type A = { a: string; }
type B = { b: string; a: undefined }
type AorB = A | B;
declare const AorB: AorB;
if (AorB.a) {
// Ok
}
Cela a du sens. PET de cerveau.
Si vous définissez a: undefined
sur le type B, vous devrez le définir sur undefined
lorsque vous créez / passez une variable.
Pour contourner cela, vous pouvez déclarer a
comme a?: undefined
, et dactylographié sera heureux si vous l'omettez.
Si je comprends bien les commentaires, cela devrait fonctionner (mais jette; testé sur le terrain de jeu): Est-ce un bug ou pas? 🤔
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'
});
Je ne comprends pas du tout cela. if ((<A>AorB).a)
n'est-il pas identique à l'utilisation de if (A.a)
parce que vous le forcez à taper A
?
Si vous définissez
a: undefined
sur le type B, vous devrez le définir surundefined
lorsque vous créez / passez une variable.
Pour contourner cela, vous pouvez déclarera
commea?: undefined
, et dactylographié sera heureux si vous l'omettez.
pourrait être mieux a?: never
, maintenant vous ne pouvez pas attribuer undefined
par erreur
Et si vous ne donnez pas de nom à chacun des membres du syndicat? (impossible de faire une assertion de type comme ci-dessus sans nom pour le type affirmé, puis-je?)
type u = "str" | {prop:"val"};
function f(arg:u){return arg.prop} // TypeScript: Property 'prop' does not exist on type 'u'
Toute solution?
je trouve une solution sur le livre:
interface A { x: number;}
interface B { y: string;}
function doStuff ( q: A | B ) {
if ( 'x' in q) {
// if type A...
}
else {
// if type B...
}
}
Extrait de: Basarat Ali Syed. «TypeScript Deep Dive.» Livres Apple.
une propriété sur un objet et peut être utilisé comme garde de type, et le TypeScript peut savoir quel type vous avez utilisé.
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
};
});
});
Le problème ici est que, comme
B
ne déclare pasa
propriétéa
de n'importe quel type possible (car vous pouvez attribuer un objet avec n'importe quel ensemble de propriétés à unB
tant qu'il a une propriétéb
de type chaîne). Vous pouvez le faire fonctionner explicitement en déclarant une propriétéa: undefined
dansB
(garantissant ainsi queB
n'aura pasa
propriététype A = { a: string; } type B = { b: string; a: undefined } type AorB = A | B; declare const AorB: AorB; if (AorB.a) { // Ok }
Cela ne fonctionne pas pour moi 07.10.2020
Et je pense que ce comportement de TS n'est pas bon car il n'aide pas beaucoup un développeur ...
Commentaire le plus utile
je trouve une solution sur le livre:
Extrait de: Basarat Ali Syed. «TypeScript Deep Dive.» Livres Apple.
une propriété sur un objet et peut être utilisé comme garde de type, et le TypeScript peut savoir quel type vous avez utilisé.