Richardson
Richardson

Reputation: 2294

How to map over an array with two different types in typescript?

I want to map over an array that has two different types, an make the map render data depending on the condition at hand.

const component = () => {

const [arr, setArr] = useState<{ arr: ({} | {id : string)[] | null }>({ arr: null });

useEffect(() => {
 setArr([{id : 1},{id : 2 },{},{},{}])
},[]}

 
return (
  <div style={{ display: "flex", flexDirection: "column" }}>
              {arr?.map((el, i) =>
                id in el ? (
                  <div key={i}>{el.id}</div>
                ) : (
                  <div>
                    {'ids to fill'}
                  </div>
                )
              )}
   </div>
 )}

CodeSandBox

Upvotes: 1

Views: 138

Answers (1)

Svetoslav Petkov
Svetoslav Petkov

Reputation: 1585

You need to use typescritp type predicates. These are functions that ensure the typescript compiler that a variable is of a certain type.

Modified working sandbox link working sandbox link

Changes to your example:

type TypeWithID = {
  id: string;
};

//type predicate function
const isOfTypeTypeWithID = (item: any): item is TypeWithID => {
  //probably more strict check
  return item.id !== undefined;
};

  const [arr, setArr] = useState<{ arr: ({} | TypeWithID)[] | null }>({
    arr: null
  });


/// rendering - now when we call the isOfTypeTypeWithID(el) , this ensures that in the "then" the element is indeed of the correct type
  return (
    <div style={{ display: "flex", flexDirection: "column" }}>
      {arr.arr?.map((el, i) =>
        isOfTypeTypeWithID(el) ? (
          <div key={i}>{el.id}</div>
        ) : (
          <div>{"ids to fill"}</div>
        )
      )}
    </div>
  );

Upvotes: 1

Related Questions