【问题标题】:Generics error, variable name does not exist on type T泛型错误,类型 T 上不存在变量名
【发布时间】:2019-07-24 20:08:53
【问题描述】:

我对 typescript 泛型有疑问。这是代码:

界面:

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
}

函数本身

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
}

这样称呼:

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

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

我得到的名称在类型上未定义(在地图中的项目上),我真的不明白

如果您有任何提示, 谢谢

【问题讨论】:

    标签: javascript typescript generics typing


    【解决方案1】:

    如果您希望能够访问T 的属性,您将需要添加一个约束。约束确保传入的任何参数都满足约束要求。

    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
    }
    

    通常不建议使用必须明确指定的泛型类型参数。如果您只有这两个选项,重载可能是更好的选择:

    
    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
    }
    
    

    【讨论】:

    • 嗯,我明白了,有没有办法确保我的变量 itemHeroItem 类型,具体取决于 &lt;T&gt; 吗?因为对我来说这就是item: T 的意思,但我一定是错的
    • @Hervé 你可以使用重载.. 我会添加一个版本
    • @Hervé 添加了版本
    • 非常感谢!该模式一点都不好,但它纯粹是关于泛型的问题。如果这段代码必须投入生产,我会分成两种方法;)
    • 您可以创建约束T extends (Hero | Item) 或从两者中提取公共INamed 接口并在约束中使用它。
    猜你喜欢
    • 1970-01-01
    • 2020-11-07
    • 2020-10-07
    • 1970-01-01
    • 2012-04-15
    • 2019-11-08
    • 2012-08-11
    • 2020-01-05
    • 2015-11-22
    相关资源
    最近更新 更多