如何修复类型“未知”在 React 打字稿中不可分配给类型“国家[]”的问题 页面/国家/地区/index.tsx服务/APIs/countries.api.tsuseAsync.tsxcomponents/InfiniteScroll.tsxservices/countries.api.ts钩子/useAsync.tsx

问题描述

我收到错误 TS2322:类型“未知”不能分配给类型“国家[]”

Error

页面/国家/地区/index.tsx

完整代码https://gitlab.com/fResult/countries-workshop/-/blob/bug/src/pages/Countries/index.tsx

import * as ApiCountries from '../../services/APIs/countries.api'

function Countries() {
  const findCountriesCallback = useCallback(() => ApiCountries.findAll(),[])
  const { execute: fetchCountries,value: countries } = useAsync(findCountriesCallback)

  useEffect(() => {
    ;(async () => await fetchCountries())()
  },[fetchCountries])

  return (
    <InfiniteScroll
      items={countries}     // I don't understand why `countries` is `unkNown` type
      renderEmptyList={() => (
        <div className="text-light-text dark:text-dark-text">
          No Content
        </div>
      )}
      keyExtractor={({ alpha3Code }) => alpha3Code}
      renderItem={renderItem}
      className="flex flex-col mt-8 md:flex-row md:flex-wrap gap-14 justify-between"
    />
  )
}

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

我认为这是三个文件

服务/APIs/countries.api.ts

(来自 https://restcountries.eu/ 的 API)

const BASE_URL = 'https://restcountries.eu/rest/v2'
export async function findAll() {
  return await fetch(`${BASE_URL}/all`)
}

export async function findByName(name: string) {
  return await fetch(`${BASE_URL}/name/${name}`)
}

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

useAsync.tsx

(这个钩子实现处理异步函数的成功和错误
完整代码https://gitlab.com/fResult/countries-workshop/-/blob/bug/src/cores/hooks/useAsync.tsx

function useAsync<T,E>(
  asyncFn: (params?: any) => Promise<Response>,immediate: boolean = true
) {
  const [value,setValue] = useState<T | Array<T> | null>(null)
  const [error,setError] = useState<E | Response | null>(null)
  const [pending,setPending] = useState(false)

  const execute = useCallback(async (params?) => {
    setPending(true)
    try {
      const response: Response = await asyncFn(params)
      if (!response.ok) {
        setError(response)
        return
      }

      setValue(await response?.json())
    } catch (err) {
      setError(err)
    }
  },[asyncFn])

  useEffect(() => {
    if (immediate) {
      ;(async () => await execute())()
    }
  },[execute,immediate])

  return { execute,value,pending,error }
}

export default useAsync

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

components/InfiniteScroll.tsx

type InfiniteScrollProps<T> = {
  items: Array<T>
  renderItem: (
    itemProps: {
      item: T
      idx: number
      array: Array<T>
      key: string | number
    },) => React.ReactNode
  renderEmptyList?: () => React.ReactNode
  keyExtractor: (item: T,idx: number) => string
  className?: string
}

function InfiniteScroll<T>({
  items,keyExtractor,renderItem,renderEmptyList,className
}: InfiniteScrollProps<T>) {
  console.log({items})
  return (
    <div className={`${className ? className: ''} infinite-scroll`}>
      {renderEmptyList && !items?.length && renderEmptyList()}
      {items?.map((item,idx,array) => {
        return renderItem({ item,array,key: keyExtractor(item,idx) })
      })}
    </div>
  )
}

export default InfiniteScroll

谁知道如何解决这个错误

================================

修正上述错误后的补充问题:

我有一个关于强类型类型转换的新问题。 现在,我将 api 函数和 useAsync 钩子的代码重构为如下... 但如果我不使用 as 关键字

,我仍然会遇到同样的错误
<InfiniteScroll
  items={countries as Array<Country>}
/>

services/countries.api.ts

import axios from 'axios'

export async function findAll(params?: {
  searchField?: string
  region?: string
}) {
  if (params?.searchField || params?.region) {
    return await axios.get(`${BASE_URL}/name/${params.searchField}`)
  }
  return await axios.get(`${BASE_URL}/all`)
}

钩子/useAsync.tsx

在这个钩子的返回值之前,我已经将强类型转换为 Array<T> | T

function useAsync<T,E>(
  asyncFn: (params?: any) => Promise<any>,setError] = useState<E | null>(null)
  const [pending,setPending] = useState(false)

  const execute = useCallback(
    async (params?) => {
      setPending(true)
      try {
        // Type casting this line before return value from this hook
        const { data }: { data: Array<T> | T } = await asyncFn(params)
        setValue(data)
      } catch (err) {
        setError(err)
        console.error('❌ Error',err.message)
      }
    },[asyncFn]
  )

  useEffect(() => {
    if (immediate) {
      ;(async () => await execute())()
    }
  },error }
}

解决方法

您需要强制转换为 any 然后将其分配给类型

const  variable = countries as any as yourtypearray

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...