问题描述
我收到错误 TS2322:类型“未知”不能分配给类型“国家[]”
页面/国家/地区/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