PAYATHON 2026

如何在 JavaScript 中为 Object.keys 查找结果正确标注类型?

数据小许

结论

在 // @ts-check 的 JavaScript 文件中,可以用 JSDoc 将团队映射标注为 Record<TEAM, readonly EMPLOYEE[]>,再单独维护一个类型为 TEAM[] 的键列表,供查找函数使用。这样,索引键和返回值都有明确的类型,也不需要使用 TypeScript 的 as 断言。

Object.keys() 返回 string[]。仅凭对象类型,TypeScript 无法确认这些键都属于 TEAM,因此直接将查找结果视为 TEAM | undefined 会产生类型错误。

JSDoc 写法

假设 EMPLOYEE 和 TEAM 是从 ./Types 导出的运行时枚举,可以在 JavaScript 文件中这样导入和使用:

import { EMPLOYEE, TEAM } from "./Types";

/** @type {Record<import("./Types").TEAM, readonly import("./Types").EMPLOYEE[]>} */
const TEAM_MEMBERS = {
  TEAM_ALPHA: [EMPLOYEE.ALICE, EMPLOYEE.BOB, EMPLOYEE.CHARLIE],
  TEAM_BETA: [EMPLOYEE.David, EMPLOYEE.Eve, EMPLOYEE.Frank],
  TEAM_GAMMA: [EMPLOYEE.Grace, EMPLOYEE.Heidi, EMPLOYEE.Ivan],
};

/** @type {import("./Types").TEAM[]} */
const TEAM_KEYS = [TEAM.TEAM_ALPHA, TEAM.TEAM_BETA, TEAM.TEAM_GAMMA];

/**
 * 根据员工查找所属团队。
 *
 * @param {import("./Types").EMPLOYEE} employee
 * @returns {import("./Types").TEAM|undefined}
 */
function getTeam(employee) {
  return TEAM_KEYS.find((team) => TEAM_MEMBERS[team].includes(employee));
}

类型如何对应

Record<TEAM, readonly EMPLOYEE[]> 要求映射包含 TEAM 中定义的团队键,并将每个团队的成员标注为 EMPLOYEE。示例中的数组使用枚举成员填充,因此元素类型与 includes(employee) 的参数类型一致。

TEAM_KEYS 列出了可查找的团队,并通过 JSDoc 标注为 TEAM[]。这样,find() 回调中的 team 类型就是 TEAM,可以合法地用作 TEAM_MEMBERS 的索引,find() 的结果类型也就是 TEAM | undefined。

如果在团队枚举中新增成员,也需要同步更新 TEAM_MEMBERS 和 TEAM_KEYS。如果不需要固定查找顺序,也可以根据 TEAM 的枚举值构造候选列表,但传给 find() 的键仍需具有 TEAM 类型。

备注:内容仅供参考。