Search code examples
arraystypescripttslint

TSLint complains about property does not exist for an element of mixed typed array


I have the following piece of code:

    interface TileA {
      imageUrl: string;
    }

    interface TileB {
      videoUrl: string;
    }

    interface TileC {
      thumbnailUrl: string;
    }

    interface Curation {
      items: (TileA | TileB | TileC)[];
    }

    const curations: Curation[] = SOME_DATA;

    curations.map((curation) => {
        curation.items.map((item) => {
          if (typeof item.videoUrl != 'undefined') {  //  getting a TS2339 complaining videoUrl is not a property
            // do something 
          }
        });
    });

and as shown, when I try to assign the property videoUrl to an item, TS complains about not a valid property? I am guessing it's because it doesn't know which actual type item is? I tried cast it to a specific Tile but the casting also result in TSLint error.

I am not sure what's the best way to handle a mixed typed array?

Thanks!


Solution

  • The function in .map() should return a value. Here's how you map a list of Bs to As:

    const aItems = items.map((item: B): A => {
        return {
            ...item,
            age: 40
        }
    });
    

    What happens here is that we clone the given item using spread syntax and assign the new age property to it.

    Moreover, if it's not necessary to have both types A and B, you could also make age an optional property and use a single type for all items:

    interface A {
      name: string;
      age?: number;
    }
    

    Edit 20/01/03:

    interface Tile {
      type: "image" | "video" | "thumbnail";
      url: string;
    }
    
    ...
    
    curations.map((curation) => {
      curation.items.map((item) => {
        switch (item.type) {
          case "image":
            // do something
            // handle case for each type
          ...
        }
    });