Versión de TypeScript: 2.1.1
Código
type A = { a: string; }
type B = { b: string; }
type AorB = A | B;
declare const AorB: AorB;
if (AorB.a) {
// use AorB.a
}
Comportamiento esperado:
El código se compila sin errores. Aunque a
no existe (necesariamente) en todos los constituyentes del sindicato, el hecho de que exista en algunos debería permitirme verificar .a
y usarlo si está presente.
Comportamiento real:
Mecanografiado se queja: "La propiedad a no existe en el tipo AorB ... La propiedad a no existe en el tipo B."
El doctor dice:
Para que funcione el mismo código, necesitaremos usar una aserción de tipo:
let pet = getSmallPet();
if ((<Fish>pet).swim) {
(<Fish>pet).swim();
}
else {
(<Bird>pet).fly();
}
http://www.typescriptlang.org/docs/handbook/advanced-types.html
Luego, en tu muestra:
if ((<A>AorB).a) {
// use AorB.a
}
El problema aquí es que debido a que B
no declara una propiedad a
, en tiempo de ejecución podría tener una propiedad a
de cualquier tipo posible (porque puede asignar una objeto con cualquier conjunto de propiedades a B
siempre que tenga una propiedad b
de tipo cadena). Puede hacer que funcione declarando explícitamente una propiedad a: undefined
en B
(asegurando así que B
no tendrá una propiedad a
aleatoria):
type A = { a: string; }
type B = { b: string; a: undefined }
type AorB = A | B;
declare const AorB: AorB;
if (AorB.a) {
// Ok
}
Tiene mucho sentido. Pedo cerebral.
Si define a: undefined
en el tipo B, tendrá que establecerlo en undefined
cuando cree / pase una variable.
Para evitar eso, puede declarar a
como a?: undefined
, y el mecanografiado estará feliz si lo omite.
Si entiendo los comentarios correctamente, esto debería funcionar (pero arroja; probado en el patio de recreo): ¿Es esto un error o no? 🤔
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'
});
No entiendo esto en absoluto. ¿No es if ((<A>AorB).a)
lo mismo que usar if (A.a)
porque lo estás forzando a volver a escribir A
?
Si define
a: undefined
en el tipo B, tendrá que establecerlo enundefined
cuando cree / pase una variable.
Para evitar eso, puede declarara
comoa?: undefined
, y el mecanografiado estará feliz si lo omite.
podría ser mejor a?: never
, ahora no puede asignar undefined
por error
¿Qué pasa si no le da un nombre a cada uno de los miembros del sindicato? (no puedo hacer una afirmación de tipo como se indicó anteriormente sin un nombre para el tipo afirmado, ¿verdad?)
type u = "str" | {prop:"val"};
function f(arg:u){return arg.prop} // TypeScript: Property 'prop' does not exist on type 'u'
¿Alguna solución?
Encuentro una solución en el libro:
interface A { x: number;}
interface B { y: string;}
function doStuff ( q: A | B ) {
if ( 'x' in q) {
// if type A...
}
else {
// if type B...
}
}
Extracto de: Basarat Ali Syed. "Análisis profundo de TypeScript". Libros de Apple.
una propiedad en un objeto y se puede usar como un tipo de protección, y TypeScript puede saber qué tipo usó.
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
};
});
});
El problema aquí es que debido a que
B
no declara una propiedada
, en tiempo de ejecución podría tener una propiedada
de cualquier tipo posible (porque puede asignar una objeto con cualquier conjunto de propiedades aB
siempre que tenga una propiedadb
de tipo cadena). Puede hacer que funcione declarando explícitamente una propiedada: undefined
enB
(asegurando así queB
no tendrá una propiedada
aleatoria):type A = { a: string; } type B = { b: string; a: undefined } type AorB = A | B; declare const AorB: AorB; if (AorB.a) { // Ok }
No me funciona 07.10.2020
Y creo que este comportamiento de TS no es bueno porque no ayuda mucho a un desarrollador ...
Comentario más útil
Encuentro una solución en el libro:
Extracto de: Basarat Ali Syed. "Análisis profundo de TypeScript". Libros de Apple.
una propiedad en un objeto y se puede usar como un tipo de protección, y TypeScript puede saber qué tipo usó.