Reputation: 41
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
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