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

如何用TypeScript实现类似RTK Query useQuery的自动类型窄化?

解决自定义Hook中isConnected与userInfo的类型关联问题

要实现类似RTK Query中useQuery的类型关联效果(通过状态标识自动推断数据的可选性),核心是用TypeScript区分联合类型把isConnected和userInfo的类型绑定起来,让TypeScript能通过状态值自动窄化数据类型。

1. 定义区分联合类型

先给Hook的返回值明确两种状态的结构:

// 定义两种互斥的返回状态类型
type UserProfileResult = 
  | { isConnected: true; userInfo: TUserInfo }
  | { isConnected: false; userInfo: undefined };

2. 调整自定义Hook的实现

修改Hook的返回逻辑,让它返回上述联合类型,无需手动断言(TypeScript会自动做类型窄化):

export const useGetUserProfile = (): UserProfileResult => {
  const userInfo = useSelector(selectUserInfo);
  
  // 当userInfo存在时,返回已连接状态
  if (userInfo !== undefined) {
    return { isConnected: true, userInfo };
  }
  
  // 否则返回未连接状态
  return { isConnected: false, userInfo: undefined };
};

注:如果selectUserInfo的返回类型是TUserInfo | undefined,当判断userInfo !== undefined时,TypeScript会自动把userInfo的类型窄化为TUserInfo,不需要额外的类型断言。

3. 使用Hook的正确姿势

现在使用Hook时,只要通过isConnected做判断,TypeScript就能自动识别userInfo的类型,不会再报“'userInfo' is possibly 'undefined'”的错误:

const { isConnected, userInfo } = useGetUserProfile();

// 写法1:if分支判断
let displayName = '!';
if (isConnected) {
  // 此处userInfo自动被推断为TUserInfo,可直接访问属性
  displayName = ' ' + userInfo.firstName;
}

// 写法2:三元表达式
const displayName = isConnected ? ' ' + userInfo.firstName : '!';

原理说明

原来的Hook返回的是普通对象类型,TypeScript无法关联isConnected和userInfo的类型关系——它只知道isConnected是布尔值,userInfo是可选值,但不知道两者的依赖关系。而区分联合类型明确了两种互斥的状态组合,TypeScript能基于isConnected的取值自动推断对应的userInfo类型。

内容的提问来源于stack exchange,提问作者Nguyễn Minh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 12:03:36