lua-language-server icon indicating copy to clipboard operation
lua-language-server copied to clipboard

Help: How can I properly write the types (@class) for a promise-like table?

Open lucastrvsn opened this issue 2 years ago • 1 comments

Hello everyone! First of all, thank you for the amazing work on this server. It's really great and extremelly fast to use!

I've a question about how can I use the type system to properly type a Promise-like table that I'm creating. Right now I need to type this piece of code:

local Promise = require ".../promise"
Promise:new(function(resolve, reject)
  -- do some async stuff...
  if some_async_true_status then
    resolve(some_async_result)
  else
    reject(some_async_error)
  end
end):next(function(result) -- < `resolve()` value here
  print(result)
end):catch(function(err) -- < `reject()` value here
  print(err)
end)

This a Promise-like implementation that I'm doing for my neovim plugin which I'm trying to get a similar API as the Javascript Promise.

My question here is, how can I type this to the callee function knows what this is going to be returned from that callback? Currently, I'm trying to play around with @generic but, I can't get the server to properly understand what I mean by my types:

local Promise = {}

---@generic T
---@class Promise<T>
---@field new(executor: fun(resolve: fun(result: T), reject: fun(err: any)))): Promise
---@field next(fn: fun(result: T)): Promise <<<<< here I'm returning `self`
---@field catch(fn: fun(err: any)): Promise <<<<< here I'm returning `self` as well

function Promise:new(executor)
  local promise = { ... }
  -- ... some operations
  return setmetatable(promise, {
    __index = self,
  })
end

function Promise:next(fn)
  -- some operations...
  return self
end

function Promise:catch(fn)
  -- some operations...
  return self
end

----------------------
-- Here is how I want to use it:

---@return Promise<string>
function my_function_that_return_promise()
  return Promise:new(function(resolve, reject)
    -- .....
    resolve("hello")
  end)
end

my_function_that_return_promise():next(function(result)
  print(result) -- << here I want the server to show `result` is a `string`
end)

For reference, this is how we can do this exactly thing using typescript:

const myPromise = new Promise<string>((resolve, reject) => {
  // ...
  resolve("hello")
})

myPromise
  .then((result) => console.log(result)) // < `result` will have `string` type
  .catch((err) => console.log(err))

Thank you for the awesome work! Sorry if I didn't make myself clear, let me know if I need to provide any further information.

lucastrvsn avatar Sep 07 '22 14:09 lucastrvsn

Dose not support generic class for now.

sumneko avatar Sep 07 '22 14:09 sumneko

i also ran into this issue recently and and just here to politely +1 this if possible :)

bandaloo avatar Jan 31 '23 19:01 bandaloo