Typescript-union på arrayer av objekter
Rotete rundt med en forening av arrays som inneholder objekter. Forventet at TS kan beskytte riktig type, men jeg antar at jeg mangler noe her:
type A = ReadonlyArray<
| { readonly __typename: 'EmbedParagraph' }
| { readonly __typename: 'EntityQueueParagraph' }
| null
> | null;
type B = ReadonlyArray<
| { readonly __typename: 'EmbedParagraph' }
| {
readonly __typename: 'EntityQueueParagraph';
readonly id: string | null;
readonly title: string | null;
}
| null
> | null;
function test(paragraphs: A | B) {
paragraphs?.forEach((paragraph) => {
/**
* TS OUTPUT:
* (parameter) paragraph: {
* readonly __typename: "EmbedParagraph";
* } | {
* readonly __typename: "EntityQueueParagraph";
* } | {
* readonly __typename: "EmbedParagraph";
* } | {
* readonly __typename: "EntityQueueParagraph";
* readonly id: string | null;
* readonly title: string | null;
* } | null
*/
if (paragraph?.__typename === 'EntityQueueParagraph') {
console.log(paragraph);
/**
* TS OUTPUT:
* (parameter) paragraph: {
* readonly __typename: "EntityQueueParagraph";
* }
*/
}
if (paragraph && 'id' in paragraph) {
console.log(paragraph);
/**
* TS OUTPUT:
* (parameter) paragraph: never
*/
}
});
}
Min tanke var at etter .__typename-sjekken, er begge alternativer tilgjengelige. Men jeg kan bare bruke entitetskøen definert i type A. Orden ser ikke ut til å være årsaken.
Det samme gjelder for den andre betingelsen, hvor jeg ville forvente at TS utleder typen B fordi id-feltet bare er tilgjengelig der.
Håper du kan gi meg et hint eller litt videre lesning. Tusen takk! mvh
REDIGER
Etter å ha lagt til en ny nøkkel til typen As EntityQueueParagraph-skriving (la til foo: number), er TS i stand til å skille de to typene... dessverre ikke brukbart for min situasjon.
Svar #1
Tilsynelatende med en map, i stedet for forEach har du allerede bedre arv. Og å endre fra paragraphs?. til paragraphs && paragraphs. når du sjekker __typename løste problemet ditt.
type A = ReadonlyArray<
| { readonly __typename: 'EmbedParagraph' }
| { readonly __typename: 'EntityQueueParagraph' }
| null
> | null;
type B = ReadonlyArray<
| { readonly __typename: 'EmbedParagraph' }
| {
readonly __typename: 'EntityQueueParagraph';
readonly id: string | null;
readonly title: string | null;
}
| null
> | null;
function test(paragraphs: A | B) {
paragraphs?.map((paragraph) => {
if (paragraph && paragraph.__typename === 'EntityQueueParagraph') {
console.log(paragraph);
}
if (paragraph && 'id' in paragraph) {
console.log(paragraph);
}
});
}
