LuaLS / LuaLS/lua-language-server
[Feature Request] Implement additional helper types
まだ誰も着手していません。
- 主要言語
- Lua
- スター
- 4.4k
- フォーク
- 442
- PR マージ指標
- 30日以内にマージされた PR はありません
説明
[!NOTE]
Just a heads up, this is gonna be a lengthy issue.
Summary
I would like to see some helper types get implemented, which would simplify writing more complex type annotations. Some of these could probably be implemented just using existing LuaCATS syntax, but others most likely need special support directly embedded into LuaLS.
This issue includes markers to track which feature is implemented and which isn't.
The types in question
-
never: Marks a function as not returning anything, and marks storing its value as an error (unlike@returns nil). -
Keys<T: table<K, V>>: ExtractsK, may create a union type -
Values<T: table<K, V>>: ExtractsV, may create a union type -
NonNilable<T>: Removesnilfrom the union typeT, making a value as required. -
Partial<T>: Returns a copy of type/classT, but with each field marked as optional / nilable. -
Required<T>: The opposite ofPartial<T>, marking all fields as required / non-nilable. -
Exclude<T, U>: Remove all types in the unionUfrom the unionT -
FunctionParameters<T: fun(...)>: Get the parameter names and types of a function. -
TypeParameters<T>: Returns a tuple of all type parameters passedT
Notes and examples
-
TypeParameters<SomeGenericType<string, integer[], boolean>>⇾ a tuple[string, integer[], boolean] -
Keys<T>andValues<T>⇾ a union type if the keys / values can have multiple types. In other words:Keys<{ foo: "abc", bar: "xyz" }>should give the type"foo"|"bar"Values<{ foo: "abc", bar: "xyz" }>should give the type"abc"|"xyz"
-
The
Partial-type should work like this:Input:
Partial<{ user_name: string, email_address: string, verified: boolean, extra_data?: table<string, Any> }>Output:
{ user_name?: string, email_address?: string, verified?: boolean, extra_data?: table<string, Any> } -
FunctionParameters<fun(name: string, age: integer)>should give the type{ name: string, age: integer }- If someone only needs the parameter names, they may use
Keys<FunctionParameters<T>>
- If someone only needs the parameter names, they may use
-
neveris useful for communicating to users of a marked function that its return values may change in the future. This is primarily used to communicate to other maintainers / your future self that they / you can change this if they / you want. -
Exclude<T, U>should only remove types fromTthat it can actually find inU. For example:Exclude<string|number|boolean|function, number|boolean>should give the typestring|functionExclude<string|number|boolean, function|userdata>should give the typestring|number|boolean, as neitherfunctionnoruserdataare inT
Implementation
These types would most likely require implementing some features from TypeScript:
- Conditional types (The TS syntax is
predicate ? T : U, butif predicate then T else Uwould probably fit in better with Lua, and potentially allow forelseifdown the line if deemed to be necessary or just a good addition; plus, LuaCATS already uses:as the inheritance-operator and?as the optional/nilable-operator). Examples:-
---@alias HasFourLegs<Animal> if Animal : { leg_count: 4 } then Animal else never ---@alias FourLeggedAnimals HasFourLegs<Bird|Dog|Ant|Wolf> --> Dog|Wolf
-
- Type indexing. Examples:
- The first type of the tuple
[string, number, boolean]could be accessed with[string, number, boolean][1] - The third parameter name
bizof the functionfun(foo, bar, biz, baz)could be retrieved withKeys<FunctionParameters<fun(foo, bar, biz, baz)>>[3] - The type of the
bizfield of the table{foo: "bar", biz: "baz"}could be accessed with{foo: "bar", biz: "baz"}["biz"]
- The first type of the tuple
Alternatively, instead of fully implementing these features, it might be enough to "simply" hard-code types like Keys and Values. It might also be a good idea to investigate allowing to write types in Lua (perhaps via plug-ins) instead.
If these are not implemented via hard-coding, the following keywords from TypeScript would most likely have to be implemented as well
-
in(for collection-like types) -
keyof
Once that's all done, some of them could be the implemented like this:
--- These were partially taken and adapted from the TypeScript docs, see:
--- https://www.typescriptlang.org/docs/handbook/utility-types.html
---@alias Keys<T> keyof T
---@alias Values<T> T[keyof T]
--- ...
---@alias NonNilable<T> if T : nil then never else T
---@alias Partial<T> { [P in Keys<T>]?: T[P]|undefined }
---@alias Required<T> { [P in keyof T]: NonNilable<T[P]> }
---@alias Exclude<T, U> if T : U then never else T
--- Not sure how this would be implemented...
---@alias FunctionParameters<T> ???
--- Same goes for this...
---@alias TypeParameters<T> ???
Considerations
I am decently familiar with LPEG grammars, so I could probably help make all of this happen if given some pointers in the right directions.
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
ソースファイルやテストは指定されていません。まず既存の LuaCATS 型構文と LPEG 文法の領域を読み、次にどのヘルパー型と実装方針について maintainer の合意が得られているかを判断してください。完了とは、明示的に範囲を定めたサブセットが、そのドキュメント化された例に対するカバレッジ付きで実装されていることを意味するものとします。現在、この issue ではその範囲が未確定のままです。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- lua
- 領域
- devtools, tooling
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 静か
- 明瞭さ
- 説明が足りない
- 初心者へのやさしさ
- 25/100