如何为动态生成的CRUD函数配置JSDoc实现IDE自动补全
问题描述
我编写了一个CrudFunctions类,可针对指定数据表生成基础CRUD操作方法。当单次实例化该类时(例如const providerService = new CrudFunctions('provider')),我配置的JSDoc可正常生效,满足IDE自动填充提示的需求。后续我可能会新增更多数据表,希望通过循环批量生成所有表对应的操作实例,避免重复编写冗余代码,当前我编写的批量生成逻辑代码如下:
const generateTableFunctions = (tableArray) => { const tableFunctions = {}; tableArray.forEach((table) => { tableFunctions[table] = new CrudFunctions(table); }); return tableFunctions; }; const foo = generateTableFunctions([ 'service', 'payment', 'certification', 'provider', 'provider_certifcation', 'provider_payment', 'provider_service' ]);
我的预期效果是:
- 输入
foo.时IDE可自动提示所有可用的表名属性 - 若无法实现该效果,至少希望输入
foo.provider.时,IDE可自动提示该实例下的getAll、getOne、add方法
我已尝试过将生成函数声明为JSDoc模板、使用@typedef定义类型等方案,但始终无法获得foo对象的正确自动补全提示。对应的CrudFunctions类实现代码如下:
/** Class representing crud functions of a given table */ class CrudFunctions { /** * @param {string} table - the name of the table from the database */ constructor(table) { this.table = table; } /** * get all items from the table * * @returns {Object} all rows from table */ async getAll() { const { rows } = await handleQuery(`SELECT * FROM ${this.table}`); return rows; } /** * gets a single item from the table * * @param {number} id - the unique id of the item we're looking up * @returns {Object} the item from the table */ async getOne(id) { const { rows } = await handleQuery( `SELECT * FROM ${this.table} WHERE ID=${id}` ); return rows; } /** * * @param {object} item - an item to be added to the table. all keys should be valid in the database already * @returns confirmation that the item got added */ async add(item) { const res = await handleQuery( buildQuery(`INSERT INTO ${this.table}`, Object.keys(item)), Object.values(item) ); return res; } }
解决方案
不需要额外依赖,纯JSDoc标注即可实现补全,分两种场景适配:
固定表列表场景(同时满足两个补全需求)
如果表列表是提前已知的固定值,通过泛型+常量类型推导即可实现表名+实例方法的双重提示,修改代码如下:
/** * @template {string} T * @param {readonly T[]} tableArray * @returns {Record<T, CrudFunctions>} */ const generateTableFunctions = (tableArray) => { const tableFunctions = /** @type {Record<T, CrudFunctions>} */ ({}); tableArray.forEach((table) => { tableFunctions[table] = new CrudFunctions(table); }); return tableFunctions; }; // 纯JS环境用@type {const}锁定数组字面量类型 const foo = generateTableFunctions(/** @type {const} */ ([ 'service', 'payment', 'certification', 'provider', 'provider_certifcation', 'provider_payment', 'provider_service' ]));
修改后输入foo.时IDE会自动枚举所有传入的表名,输入foo.provider.时也会正常提示CrudFunctions类下的所有公开方法。如果是TS项目,把/** @type {const} */替换为数组后的as const即可。
动态表列表场景(保底满足实例方法提示)
如果表列表是运行时动态获取、无法提前固定,只需要给返回值标注统一索引类型即可。这种场景下无法提前提示具体表名,但访问任意表属性后都能正常识别为CrudFunctions实例,提示CRUD方法:
/** * @param {string[]} tableArray * @returns {Record<string, CrudFunctions>} */ const generateTableFunctions = (tableArray) => { const tableFunctions = /** @type {Record<string, CrudFunctions>} */ ({}); tableArray.forEach((table) => { tableFunctions[table] = new CrudFunctions(table); }); return tableFunctions; };
内容的提问来源于stack exchange,提问作者Bob Nearents
相关产品推荐
相关产品推荐

