TypeScript无法确定自定义useDelay Hook返回值类型的原因咨询
TypeScript推断自定义Hook返回值为联合类型的问题
先看这个自定义Hook,它会将状态设为true,并在2秒后重置为false:
import { useState, useRef } from 'react'; export const useDelay = () => { const [loading, setIsLoading] = useState(false); const timer = useRef(null); const runDelay = () => { setIsLoading(true); timer.current = setTimeout(() => { setIsLoading(false); }, 2000); } return [loading, runDelay]; }
但使用这个Hook时,TypeScript会错误地将loading推断为boolean | (() => void)类型:
const [loading, runDelay] = useDelay(); // const loading: boolean | (() => void)
原因分析
TypeScript对数组的默认推断逻辑是:把数组推断为所有元素类型的联合类型数组,也就是(boolean | (() => void))[],而不是固定长度、固定顺序的元组类型。因此解构时,每个变量都会被认为可能是联合类型中的任意一种。
解决方案
方案一:显式指定Hook的返回类型
直接给Hook添加返回类型标注,明确返回的是[boolean, () => void]元组:
import { useState, useRef } from 'react'; export const useDelay = (): [boolean, () => void] => { const [loading, setIsLoading] = useState(false); const timer = useRef<NodeJS.Timeout | null>(null); const runDelay = () => { setIsLoading(true); timer.current = setTimeout(() => { setIsLoading(false); }, 2000); } return [loading, runDelay]; }
方案二:使用as const断言返回值
在返回语句中添加as const,让TypeScript将数组推断为只读元组,从而保留每个元素的具体类型和顺序:
import { useState, useRef } from 'react'; export const useDelay = () => { const [loading, setIsLoading] = useState(false); const timer = useRef<NodeJS.Timeout | null>(null); const runDelay = () => { setIsLoading(true); timer.current = setTimeout(() => { setIsLoading(false); }, 2000); } return [loading, runDelay] as const; }
注:我知道在useEffect清理函数中清理定时器是最佳实践,这是一个未完成的Hook :)
内容的提问来源于stack exchange,提问作者Kipnoedels
相关产品推荐
相关产品推荐

