Por ejemplo, tengo un código de este tipo:
interface Subscriber { reviewData: string | string[] hasArray: boolean; } const reviews = ["Good", "Not bad"]; const subscriber: Subscriber = { reviewData: reviews, hasArray: Array.isArray(reviews) } if (subscriber.hasArray) { subscriber.reviewData.forEach(console.log); } else { console.log(subscriber.reviewData); } Por supuesto, TypeScript se quejará en subscriber.reviewData.forEach(console.log); diciendo que no puede definir si es una matriz o solo una cadena porque no hay suficiente tipo de protección en la condición subscriber.hasArray .
No quiero escribir siempre Array.isArray(subscriber.reviewData) porque voy a usar esta lógica en muchos otros lugares.
He oído hablar de is , pero ese no es realmente el caso en mi escenario porque usar is implica que debe tener una función y pasarle algún argumento.
¿Cómo puedo lograr el resultado deseado?
Si desea poder usar hasArray como una forma de determinar si reviewData es una string[] o una string , entonces realmente desea que Subscriber sea un tipo de unión discriminado en lugar de una interfaz. Su interfaz permitiría {reviewData: "", hasArray: true} , por lo que el compilador no puede descartar la posibilidad. Con una unión discriminada, puede tener una propiedad discriminante que verifica para restringir el tipo de todo el objeto:
type Subscriber = { reviewData: string[] hasArray: true; } | { reviewData: string hasArray: false; } En este caso hasArray es la propiedad discriminante de un literal booleano de tipo true o false .
Entonces, dado un Subscriber :
const subscriber: Subscriber = Math.random() < 0.5 ? { reviewData: "Good", hasArray: false } : { reviewData: ["Who", "Cares"], hasArray: true };Podemos verificarlo de la manera que desee sin error del compilador:
if (subscriber.hasArray) { subscriber.reviewData.forEach(console.log); } else { console.log(subscriber.reviewData.toUpperCase()); }