Skip to content

Type cast and type narrow proposal #1030

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sumneko opened this issue Apr 9, 2022 · 6 comments
Closed

Type cast and type narrow proposal #1030

sumneko opened this issue Apr 9, 2022 · 6 comments
Labels
feat/type check Related to the type checking feature help wanted Extra attention is needed

Comments

@sumneko
Copy link
Collaborator

sumneko commented Apr 9, 2022

Version 1 (deprecated)
---@type boolean|string
local x

if xxx then
    -- type cast
    print(string.len(x--[[---@type string]]))
    print(string.len(x--[[@type string]]))
    print(string.len(x--[[: string]]))

    print(string.len(x--[[---@not boolean]]))
    print(string.len(x--[[@not boolean]]))
    print(string.len(x--[[: !boolean]]))
end
---@type string|boolean
local x

if type(x) == 'string' then
    ---@narrow x string # x is `string` in *this block*
    -- auto narrow in the future
    print(string.len(x))
end

print(x) -- x is `string|boolean` here
---@type string|boolean
Global = XXX

if type(Global) == 'string' then
    ---@narrow Global string  # Global is `string` in *this block*
    -- auto narrow in the future
    print(string.len(Global))
end

print(Global) -- Global is `string|boolean` here
---@param x string|integer
local function upper(x)
    if type(x) == 'integer' then
        x = tostring(x)
    end
    ---@narrow x string #auto narrow in the future
    return x:upper()
end

Due to Lua's syntax, using inline comments can be verbose and ugly.
Is there any other method based on line comments?

EDIT: ---@narrow will affect all the block and must declare at the top of block

Version 2
local loc
tonumber(loc--[[@as string]]) -- Just as the last way of type cast

if  type(loc)           == 'string'
and type(Global)        == 'string'
and type(xx.yy)         == 'string'
and type(getClass().zz) == 'string' then
    ---@as loc string, Global string, xx.yy string # can not narrow `getClass().zz`
    -- Will auto type cast in this case
    -- Use `---@as` or `---@narrow` or `---@cast` ?
end
Version 3
  • Support limited operations
---@type integer
local x --> x: integer

---@cast x boolean
print(x) --> x: boolean

---@cast x +string, +integer
print(x) --> x: boolean|string|integer

---@cast x -integer, -boolean
print(x) --> x: string

---@cast x +?
print(x) --> x: string?

---@cast x -?
print(x) --> x: string
@sumneko sumneko added help wanted Extra attention is needed feat/type check Related to the type checking feature labels Apr 9, 2022
@CppCXY
Copy link
Collaborator

CppCXY commented Apr 9, 2022

string.len(x--[[@as string]])
string.len(x) ---@narrow x as string
---@narrow x as string
string.len(x)

@fesily
Copy link
Contributor

fesily commented Apr 11, 2022

string.len(x) ---@as x string
---@as x string
string.len(x) 
local x

if type(x) == 'string' then
    ---@as x string # x is `string` in *this block*
    -- auto narrow in the future
    print(string.len(x))
end

@sumneko
Copy link
Collaborator Author

sumneko commented Apr 11, 2022

string.len(x--[[@as string]]) string.len(x) ---@narrow x as string ---@narrow x as string string.len(x)

Why need as in ---@narrow x as string ?

@sumneko sumneko pinned this issue Apr 14, 2022
@disco0
Copy link

disco0 commented Jun 3, 2022

In a similar vein w/ fesily's example: are guards outside the scope of this proposal/too much semantically? Basic example case:

---@param  value unknown
---@return value is string
function is_string(value)
    return typeof(value) == "string"
end

---@type unknown
local value

if is_string(value) then
    print(value.len(x))
end

Alternatively, more inline w/ proposal syntax (possible conflict with multiple return syntax, however I don't think + is valid normally?):

---@param  value unknown
---@return value +string
function is_string(value)
    return typeof(value) == "string"
end

@sumneko
Copy link
Collaborator Author

sumneko commented Jun 15, 2022

In a similar vein w/ fesily's example: are guards outside the scope of this proposal/too much semantically? Basic example case:

---@param  value unknown
---@return value is string
function is_string(value)
    return typeof(value) == "string"
end

---@type unknown
local value

if is_string(value) then
    print(value.len(x))
end

Alternatively, more inline w/ proposal syntax (possible conflict with multiple return syntax, however I don't think + is valid normally?):

---@param  value unknown
---@return value +string
function is_string(value)
    return typeof(value) == "string"
end

I think it should be something like:

---@generic V
---@param value V
---@return V is string
function is_string(value)
    return typeof(value) == "string"
end

But it is hard to implement

@sumneko
Copy link
Collaborator Author

sumneko commented Jun 25, 2022

Version 3 has been implemented. Please open new issues if there are other problems

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat/type check Related to the type checking feature help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants