场景
在目前的前端社区中,已经有越来越多的人使用typescript来编写项目。在这里笔者就不单独介绍typescript的优点及使用了,掘金上有一堆的文章,你可以自行去搜索相关的教程。
本篇文章主要讲述如何在react-query中使用typescript。
实践
对查询函数返回值定义类型
最简单的使用方法是,在传入的查询函数中,标记返回数据的数据类型,这样最后读取data属性值也是该数据类型。
interface Issue {
id:number;
title:string;
number:number;
body:string;
state: "open" | "closed";
}
const Issues = ({org, repo}:{org:string, repo:string}) => {
const issuesQuery = useQuery(
["issues", org, repo],
async () => {
const response = await fetch(
`https://api.github.com/repos/${org}/${repo}/issues`
)
// ①
const json: Issue[] = await response.json()
return json;
}
)
console.log(issuesQuery.data) // Issue[] | undefined
// ...
}
①:在这里将后端返回的数据json定义为Issue[]类型,此时你再获取数据时,Issues.data的数据类型也是相同的。
在这里需要注意的是,
Issues.data的数据类型不止是Issue[]类型,它同样也具有undefined类型,因为在第一次获取数据时,Issues.data默认为undefined。
那么react-query是怎么推断出数据属性类型的呢?
react-query会使用一个泛型并自动推断其类型作为查询函数的返回类型。如果你想验证查询函数是否返回正确的类型,可以将一个类型作为第一个泛型参数传递给useQuery。如果类型不匹配,TypeScript会返回一个警告。
const issuesQuery = useQuery<Issue[]>(
["issues", org, repo],
// Type Error: Type 'string[]' is not assignable to type 'Issue[]'
async () => {
const response = await fetch(
`https://api.github.com/repos/${org}/${repo}/issues`
)
const json: string[] = await response.json()
return json;
}
)
对抛出的错误定义类型
快速回顾一下在日常开发中TypeScript如何正常处理错误。
当你在JavaScript中抛出任何东西时,你可以使用try{} catch{}在任何地方捕获该错误。错误作为参数传递给catch,类似于下面的代码:
try {
throw new Error("Something went wrong")
} catch (error) {}
如果你正在调用许多三方库或者其它的一些函数方法,TypeScript🈶可能无法推断出错误的类型。因此这个error隐含了any类型,这将导致typescript失去用武之地。因此从TypeScript 4.4开始,任何被获取的error都是unknown类型,所以可以使用instanceof操作符来查看是否是一个错误。示例代码如下:
try {
throw new Error("Something went wrong")
} catch (error) {
if (error instanceof Error) {
console.error(error.message)
}
}
那么在react-query中该如何处理错误呢?答案是你只需要在useQuery的第二个泛型中传入错误的类型即可,类似于下面的代码:
const issuesQuery = useQuery<Issue[], Error>(
["issues", org, repo],
async () => {
const response = await fetch(
`https://api.github.com/repos/${org}/${repo}/issues`
)
const json: Issue[] = await response.json()
return json;
}
)
console.log(issuesQuery.error) // Error | undefined
Error类型可以随意自定义,如果不传入定义的错误类型,此时默认的类型就是上文所述的unknown。
使用select配置项的数据类型定义
还记得在react-query手把手教程19-渲染优化这篇文章中介绍的select配置项么?它可以很好的对我们的数据进行转换。但是也会造成一个问题,如何对转换后的数据进行类型定义,此时你就需要用到useQuery钩子的第三个泛型:
const issuesQuery = useQuery<Issue[], Error, string[]>(
["issues", org, repo],
async () => {
const response = await fetch(
`https://api.github.com/repos/${org}/${repo}/issues`
)
const json: string[] = await response.json()
return json;
},
{
select: (data: Issue[]) => data.map(issue => issue.title)
}
)
在这里我们需要回顾一下,第一个泛型是查询函数返回的数据是否符合定义,第二个泛型是定义错误的数据类型,第三个泛型是通过select配置项处理后,实际你获得的issuesQuery.data的类型(如果没有select配置项,那么第一个泛型就是最后issuesQuery.data的类型)。
对查询键进行类型定义
在多数情况下,查询键的默认定义是readonly unknown[]这样可以覆盖所有传入的查询键类型。
在react-query中,你可以将传入的查询键,用as const设置为元组,让typescript自己检测出类型即可,类似于下面的代码:
const [pageNum, setPageNum] = useState(1);
const issuesQuery = useQuery(
["issues", org, repo, {page: pageNum}] as const,
async ({queryKey}) => {
// parameter queryKey:
// readonly ["issues", string, string, {page :number}]
// ...
}
)
到这里对于react-query与typescript的结合使用就结束了,已经可以覆盖你大多数的使用场景了,如果需要学习更多,可以去官网深入学习。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 29 天,点击查看活动详情