如何在JavaScript中基于请求字段实现API响应类型安全?
实现API响应的类型安全方案
原生JavaScript本身不具备静态类型检查能力,要实现类型安全,最直接的方案是使用TypeScript;如果暂时不想迁移到TS,也可以通过JSDoc在编辑器中获得类型提示。以下是两种场景的具体实现:
一、TypeScript 实现方案
1. 定义字段映射与核心类型
先把数字标识和字段名的映射用枚举定义,再创建工具类型,根据传入的字段数组动态生成返回类型:
// 定义数字标识对应字段名的枚举 enum FieldId { FirstName = 1, LastName = 2, Age = 3, Address = 4, Email = 5 } // 定义所有字段的完整类型 type UserFullFields = { firstname: string | null; lastname: string | null; age: number | null; address: string | null; email: string | null; }; // 工具类型:根据传入的字段ID数组,提取对应的返回类型 type PickUserFields<T extends FieldId[]> = { [K in keyof UserFullFields as T[number] extends FieldId[K] ? K : never]: UserFullFields[K]; };
2. 改造请求函数,添加类型约束
让server函数接收指定的FieldId数组,并返回对应的动态类型:
function server<T extends FieldId[]>(fields: T): PickUserFields<T> { const allFields: Record<FieldId, keyof UserFullFields> = { [FieldId.FirstName]: 'firstname', [FieldId.LastName]: 'lastname', [FieldId.Age]: 'age', [FieldId.Address]: 'address', [FieldId.Email]: 'email' }; const result = {} as PickUserFields<T>; fields.forEach(field => { if (allFields[field]) { result[allFields[field]] = null; } }); return result; } // 使用示例: const response = server([FieldId.FirstName, FieldId.Age]); // 此时response的类型为 { firstname: string | null; age: number | null },编辑器会自动做类型检查和提示
二、JavaScript 结合 JSDoc 实现类型提示
如果项目暂时无法迁移到TypeScript,可以用JSDoc注释为函数添加类型约束,在VSCode等编辑器中获得类型提示:
/** * @typedef {Object} UserFullFields * @property {string|null} firstname * @property {string|null} lastname * @property {number|null} age * @property {string|null} address * @property {string|null} email */ /** * @typedef {1|2|3|4|5} FieldId */ /** * @template {FieldId[]} T * @param {T} fields * @returns {Pick<UserFullFields, T[number] extends 1 ? 'firstname' : T[number] extends 2 ? 'lastname' : T[number] extends 3 ? 'age' : T[number] extends 4 ? 'address' : 'email'>} */ function server(fields) { const allFields = { 1: 'firstname', 2: 'lastname', 3: 'age', 4: 'address', 5: 'email' }; const result = {}; fields.forEach(field => { if (allFields[field]) { result[allFields[field]] = null; } }); return result; } // 使用示例: const response = server([1, 3]); // 编辑器会提示response包含firstname和age字段,具备类型提示能力
内容的提问来源于stack exchange,提问作者Jon You
相关产品推荐
相关产品推荐

