为Lua多表合并函数加类型注解,实现sumneko-lua LSP键追踪
为Lua合并函数添加泛型类型注解,让sumneko-lua LSP追踪table属性
我想给Lua的合并函数添加泛型类型注解,让sumneko-lua LSP能正确追踪所有参与合并的table的属性。示例如下:
local foo = { a = true } local bar = { b = true } -- merge是需要添加类型注解的函数 local fooBar = merge(foo, bar)
我希望fooBar的类型被识别为{a: boolean, b: boolean}。理想状态下该函数可接受任意数量的table合并,如果无法实现,写固定数量的重载也可以。
以下是我尝试过但无效的代码:
---@generic T ---@generic A { [string]: T } ---@generic O { [string]: T } ---@param ... O|A ---@return O function M.merge(...) ---Assigns the properties of one or more objects to another object ---@generic X ---@generic Y ---@generic A { [string]: X } ---@generic B { [string]: Y } ---@generic O { [string]: X | Y } ---@param a A ---@param b B ---@return O function M.merge(a, b)
解决方案
1. 固定数量参数的重载实现(精确匹配)
sumneko-lua支持函数重载,你可以为不同参数数量的场景分别定义泛型注解,让LSP精确识别合并后的类型。比如实现2到4个参数的重载:
---@generic A, B ---@param a A ---@param b B ---@return A & B function M.merge(a, b) end ---@generic A, B, C ---@param a A ---@param b B ---@param c C ---@return A & B & C function M.merge(a, b, c) end ---@generic A, B, C, D ---@param a A ---@param b B ---@param c C ---@param d D ---@return A & B & C & D function M.merge(a, b, c, d) end -- 实际实现逻辑 function M.merge(...) local result = {} for _, tbl in ipairs({...}) do for k, v in pairs(tbl) do result[k] = v end end return result end
调用merge(foo, bar)时,fooBar会被正确识别为{a: boolean} & {b: boolean},等价于{a: boolean, b: boolean}。
2. 任意数量参数的近似实现
如果想要支持任意数量的table,sumneko-lua目前无法完全精确推导所有属性,但可以用泛型约束来近似实现:
---@generic T: table ---@param ... T ---@return T function M.merge(...) local result = {} for _, tbl in ipairs({...}) do for k, v in pairs(tbl) do result[k] = v end end return result end
这种方式下,LSP会把返回值识别为所有输入table的联合类型,虽然不会逐个列出所有属性,但能识别出所有可能的键和对应类型。
之前尝试无效的原因
- 第一种写法中,泛型
A和O都被约束为{[string]: T},要求所有输入table的value类型必须一致,且返回值只能是单一的O类型,无法合并不同结构的table。 - 第二种写法中,
O被定义为{[string]: X | Y},仅合并了value类型,没有保留具体的键名,导致LSP无法识别a、b这类具体属性。
内容的提问来源于stack exchange,提问作者Danielo515
相关产品推荐
相关产品推荐

