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

TypeScript中如何实现数组过滤时的精确联合类型推断?

解决方案

要让filteredUsers被正确推断为type属性为UserType.PUBLISHER | UserType.VIEWER的User数组,需要从两个方面调整代码:

1. 让userTypes的类型更精确

TypeScript默认会把userTypes推断为宽泛的UserType[],我们需要让它保留具体元素的联合类型,最简便的方式是使用as const断言:

const userTypes = [UserType.PUBLISHER, UserType.VIEWER] as const;

这样userTypes的类型会被推断为readonly [UserType.PUBLISHER, UserType.VIEWER],对应的联合类型就是UserType.PUBLISHER | UserType.VIEWER。

2. 给getUsersByTypes添加泛型和类型守卫

原函数的filter方法无法自动缩小返回数组的元素类型,我们需要通过泛型捕获传入类型的具体信息,再用类型守卫告诉TypeScript过滤后的元素类型:

const getUsersByTypes = <T extends UserType>(users: User[], types: readonly T[]) => {
  // 类型守卫:断言返回true时,user的type属性是T类型
  return users.filter((user): user is User & { type: T } => {
    return types.includes(user.type as T);
  });
};

完整代码示例

enum UserType {
  ADMIN,
  VIEWER,
  PUBLISHER,
}

interface User {
  name: string;
  type: UserType;
}

// 用as const让类型更精确
const userTypes = [UserType.PUBLISHER, UserType.VIEWER] as const;

const users = [
  { name: 'Paul', type: UserType.ADMIN },
  { name: 'Steve', type: UserType.VIEWER },
  { name: 'Marry', type: UserType.PUBLISHER },
];

// 带泛型和类型守卫的过滤函数
const getUsersByTypes = <T extends UserType>(users: User[], types: readonly T[]) => {
  return users.filter((user): user is User & { type: T } => {
    return types.includes(user.type as T);
  });
};

// 现在filteredUsers的类型是(User & { type: UserType.PUBLISHER | UserType.VIEWER })[]
const filteredUsers = getUsersByTypes(users, userTypes);

补充说明

  • 如果你不想使用as const,也可以显式标注userTypes的类型,效果一致:
    const userTypes: readonly (UserType.PUBLISHER | UserType.VIEWER)[] = [UserType.PUBLISHER, UserType.VIEWER];
    
  • 泛型T extends UserType确保传入的types只能是UserType的合法子集,避免传入无效值。

内容的提问来源于stack exchange,提问作者Antek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 22:40:25