TypeScript中如何推导泛型回调函数的返回类型
问题原因
你当前的类型推导失效的核心原因是createContext函数仅定义了Provider入参的泛型T,且显式将useHook的返回值标注为any,导致ReturnType<typeof useHook>获取到的结果始终为any,完全丢失了回调返回值的类型信息。
修复后的完整代码
import { FC, createElement, useState, useMemo, createContext as _context, useContext as _useContext } from 'react'; // 新增第二个泛型R,对应useHook的返回值类型 const createContext = <T, R>(useHook: (providerProps: T) => R) => { // 给React.createContext指定泛型为R,用类型断言做初始值占位 const ctx = _context({} as R); const Provider: FC<T & { children?: React.ReactNode }> = ({ children, ...props }) => { const value = useHook(props as T); return createElement(ctx.Provider, { value }, children); }; const useContext = () => _useContext(ctx); const createProvider = (displayName: string) => { Provider.displayName = displayName; return Provider; }; return { useContext, createProvider, }; }; const ctx = createContext(({ _theme }: { _theme: 'light' | 'dark' }) => { const [theme, setTheme] = useState(_theme); return useMemo(() => ({ theme, setTheme }), [theme]); }); export const AppThemeProvider = ctx.createProvider('AppThemeProvider'); const useAppTheme = () => { // 此时theme会自动推导为 'light' | 'dark' 类型,setTheme类型也完全正确 const { theme } = ctx.useContext(); return theme; };
核心修改点
- 为
createContext新增第二个泛型参数R,用来对应你传入的自定义hook的返回值类型,TS会根据你传入的回调自动推导R的类型,不需要手动声明 - 将
useHook的返回值类型从any改为泛型R,保留完整类型信息 - 创建原始Context时指定泛型为
R,避免默认的空对象类型干扰后续类型推导 - 不需要额外的
as ReturnType断言,Context返回值类型会自动和你传入的hook返回值完全对齐
可选增强
如果需要避免在Provider外使用useContext导致的取值错误,可以给useContext加一层运行时判断:
const useContext = () => { const context = _useContext(ctx); if (Object.keys(context).length === 0) { throw new Error('useContext must be used within the corresponding Provider'); } return context; };
内容的提问来源于stack exchange,提问作者Miguel Bogota
相关产品推荐
相关产品推荐

