typing recursive function with nested type
Question:
background: solving some algorithm problem
Problem
I’m trying to use a recursive function with nested type in VSCode, and it keep throwing error to me. I reduced it to this
from typing import Type
NestedStr = list[str | Type["NestedStr"]]
def get_first(x: str | NestedStr) -> str:
if isinstance(x, str):
return x
return get_first(x[0]) # Argument of type "str | NestedStr" cannot be assigned to parameter "x" of type "str | NestedStr" in function "get_first"
assert get_first(["a", "b"]) == "a" # No error thrown here
assert get_first([["a", "b"]]) == "a" # Argument of type "list[list[str]]" cannot be assigned to parameter "x" of type "str | NestedStr" in function "get_first"
Obviously, when x
is not an str
it should be a NestedStr
hence it can be an infinite nested list but pylance seems not knowing it.
The code can run perfectly but the error is annoying. Is there anyway to suppress it (except "type: ignore")?
Related
Appendices
Full Error Messages
- on recursive call
get_first(x[0])
Argument of type "str | NestedStr" cannot be assigned to parameter "x" of type "str | NestedStr" in function "get_first"
Type "str | NestedStr" cannot be assigned to type "str | NestedStr"
Type "NestedStr" cannot be assigned to type "str | NestedStr"
"Type[type]" is incompatible with "Type[str]"
"Type[type]" is incompatible with "NestedStr" Pylance reportGeneralTypeIssues
- on call with
list[list[str]]
Argument of type "list[list[str]]" cannot be assigned to parameter "x" of type "str | NestedStr" in function "get_first"
Type "list[str]" cannot be assigned to type "str | NestedStr"
"list[str]" is incompatible with "str"
Type "list[str]" cannot be assigned to type "NestedStr" Pylance reportGeneralTypeIssues
Answers:
In my view this NestedStr = list[str | Type["NestedStr"]]
has to be changed to that NestedStr = list[str | "NestedStr"]
, as it is either a string or a concrete instance of NestedStr, but not the plain type. I haven’t checked with pylance, but mypy accepts that and doesn’t raise any issue.
As in Pylance v2023.3.20
@Simon Hawe’s answer throws an error "NestedStr" is not defined Pylance (reportUndefinedVariable)
The current solution is like this:
from typing import Union
NestedStr = list[Union[str, "NestedStr"]]
def get_first(x: str | NestedStr) -> str:
if isinstance(x, str):
return x
return get_first(x[0])
# or the shorter and working version in next line:
# return x if isinstance(x, str) else get_first(x[0])
assert get_first([["a", "b"]]) == "a"
background: solving some algorithm problem
Problem
I’m trying to use a recursive function with nested type in VSCode, and it keep throwing error to me. I reduced it to this
from typing import Type
NestedStr = list[str | Type["NestedStr"]]
def get_first(x: str | NestedStr) -> str:
if isinstance(x, str):
return x
return get_first(x[0]) # Argument of type "str | NestedStr" cannot be assigned to parameter "x" of type "str | NestedStr" in function "get_first"
assert get_first(["a", "b"]) == "a" # No error thrown here
assert get_first([["a", "b"]]) == "a" # Argument of type "list[list[str]]" cannot be assigned to parameter "x" of type "str | NestedStr" in function "get_first"
Obviously, when x
is not an str
it should be a NestedStr
hence it can be an infinite nested list but pylance seems not knowing it.
The code can run perfectly but the error is annoying. Is there anyway to suppress it (except "type: ignore")?
Related
Appendices
Full Error Messages
- on recursive call
get_first(x[0])
Argument of type "str | NestedStr" cannot be assigned to parameter "x" of type "str | NestedStr" in function "get_first"
Type "str | NestedStr" cannot be assigned to type "str | NestedStr"
Type "NestedStr" cannot be assigned to type "str | NestedStr"
"Type[type]" is incompatible with "Type[str]"
"Type[type]" is incompatible with "NestedStr" Pylance reportGeneralTypeIssues
- on call with
list[list[str]]
Argument of type "list[list[str]]" cannot be assigned to parameter "x" of type "str | NestedStr" in function "get_first"
Type "list[str]" cannot be assigned to type "str | NestedStr"
"list[str]" is incompatible with "str"
Type "list[str]" cannot be assigned to type "NestedStr" Pylance reportGeneralTypeIssues
In my view this NestedStr = list[str | Type["NestedStr"]]
has to be changed to that NestedStr = list[str | "NestedStr"]
, as it is either a string or a concrete instance of NestedStr, but not the plain type. I haven’t checked with pylance, but mypy accepts that and doesn’t raise any issue.
As in Pylance v2023.3.20
@Simon Hawe’s answer throws an error "NestedStr" is not defined Pylance (reportUndefinedVariable)
The current solution is like this:
from typing import Union
NestedStr = list[Union[str, "NestedStr"]]
def get_first(x: str | NestedStr) -> str:
if isinstance(x, str):
return x
return get_first(x[0])
# or the shorter and working version in next line:
# return x if isinstance(x, str) else get_first(x[0])
assert get_first([["a", "b"]]) == "a"