Hervé
Hervé

Reputation: 41

Generics error, variable name does not exist on type T

i have a problem with typescript generics. here is the code :

interface :

export interface Hero {
  id: number
  name: string
  localized_name: string
  avatar: string
}

export interface Item {
  id: number
  name: string
  cost: number
  secret_shop: boolean
  side_shop: boolean
  recipe: boolean
  localized_name: string
  avatar: string
}

the function itself

export const getContent = async <T>(genre: string): Promise<T[]> => {
  const res = await fetch(`${apiEndpoint}${genre})
  const response = await res.json()
  const defaultContent = response.result[category]
  const contentWithImage = defaultContent.map((item: T) => {
    const contentImageUrl = `${imgURL}${item.name.replace('__', '')}.png`

    return { ...item,  avatar: contentImageUrl }
  })
  return contentWithImage
}

called this way :

const heroes = await getContent<Hero>('heroes')

or

const items = await getContent<Hero>('items')

i get a name is undefined on type (on item within map) and i really don't get it

if you have any hints, thanks

Upvotes: 0

Views: 217

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249466

If you want to be able to access properties of T you will need to add a constraint. A constraint ensures that any argument passed in meets the constraint requirements.

export const getContent = async <T extends { name : string }>(genre: string): Promise<T[]> => {
  const res = await fetch(`${apiEndpoint}${genre}`)
  const response = await res.json()
  const defaultContent = response.result[category]
  const contentWithImage = defaultContent.map((item: T) => {
    const contentImageUrl = `${imgURL}${item.name.replace('__', '')}.png`

    return { ...item,  avatar: contentImageUrl }
  })
  return contentWithImage
}

Having generic type parameters that must be specified explicitly is usually not recommended. If you just have these two options, overloads might be a better choice:


async function getContent (genre: "heroes"): Promise<Hero[]>
async function getContent (genre: "items"): Promise<Item[]> 
async function getContent (genre: string): Promise<(Item | Hero)[]>{
  const res = await fetch(`${apiEndpoint}${genre}`)
  const response = await res.json()
  const defaultContent = response.result[category]
  const contentWithImage = defaultContent.map((item: Item | Hero) => {
    const contentImageUrl = `${imgURL}${item.name.replace('__', '')}.png`

    return { ...item,  avatar: contentImageUrl }
  })
  return contentWithImage
}

Upvotes: 1

Related Questions