Home > database >  correct typeguard for union object array iteration
correct typeguard for union object array iteration

Time:05-26

type A = ~~;
type B = ~~;
type C = ~~;

function isA(a: string) a is A{
   return a in A
}

I have three type or enum and I want to iterate array of U to make another array.

const arr1 = A|B|C[] // array that item's type is A|B|C
const arr2 = arr1.map(item=>{
   if(isA(item)){
     return {a: 1};
   }
   if(isB(item)){
      return {b:1};
   }
   if(isC(item)){
      return {c:1}
   }
}

IDE inferenced map value item as A|B|C correctly

Problem is that when I do typeguard with if state, the result array item type contains 'undefined' type.

arr2 = ({a:1}|{b:1}|{c:1}|undefined)[]//like this

Anyway I could hint typescript that item does not contains undefined value??

CodePudding user response:

You've got a case where the predicate returns undefined (when item is not A, B, or C somehow):

const arr2 = arr1.map(item=>{
   if(isA(item)){
     return {a: 1};
   }
   if(isB(item)){
      return {b:1};
   }
   if(isC(item)){
      return {c:1}
   }
}

TS thinks it might return undefined. To assert that it shouldn't, you could throw an error:

const arr2 = arr1.map(item=>{
   if(isA(item)){
     return {a: 1};
   }
   if(isB(item)){
      return {b:1};
   }
   if(isC(item)){
      return {c:1}
   }
   throw new Error("Why did this happen?");
}

Now the return type is A | B | C | never, which simplifies to A | B | C.

  • Related