You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 01:25:31