Pylance introduces five new features that enable type magic for Python developers


In last week’s Pylance update we introduced Semantic colorization, and thank you for all feedback! It was exciting for the team to bring this new feature to you. With the latest release of Pylance (version 2020.9.4) we are excited to introduce features that bring us closer to the goal of helping developers write correct Python code faster and more easily.

1.      Support for recursive type aliases

With recursive types aliases, you can now specify types for complex scenarios in a natural, succinct, and intuitive manner. For example, expressing a structure to capture my settings for VS Code can be as simple and elegant as in the example below. For data structures that have a tree pattern, a recursive type alias offers a neat solution.

ConfigValue = Union[
    Dict[str, "ConfigValue"],
config: List[ConfigValue] = [
        ["Experiment1", "Experiment13", "Experiment56", "Experiment106"]},
    {"python.formatting.provider": "black"},
    {"python.formatting.blackArgs": ["--line-length", "130"]},
    {"python.sortImports.args": ["-rc", "-sp isort.cfg"]},

2.      Getter and setter mismatches.

Property type mismatch will catch cases where getter and the setter of @property are mismatched. This is an easy mistake to make, and now Pylance can help you avoid this situation. The type analyzer will verify that the type of the “value” parameter passed to the setter is assignable to the type returned by the getter.

    def prop_3(self) -> List[_T]:
        return []

    # This should generate an error because _T is
    # not assignable to List[_T].

    def prop_3(self, value: _T) -> None:

3.      Help with getting generics right

New type checks for generics will help you catch errors and give you appropriate messages that can help you correct them. PEP 484 says that a type variable should not be used in a context where it has no meaning. For example, if you annotate a local variable with the type List[T] but T is not used by the containing generic function or generic class, then T has no meaning in this context and should be flagged as an error.


4.      Support for so-called “higher-kinded type variables”

The feature allows you to pass a generic class or function to a generic function, and the type variable solver will solve for both levels of type variables.

T = TypeVar("T")
U = TypeVar("U")

def identity(x: T) -> T:
    return x

# fmap() requires the same type as the parameter in the callable and
# the type for maybe

def fmap(f: Callable[[T], U], maybe: Optional[T]) -> Optional[U]:
    return None

def func(x: int):
    y = fmap(identity, x) # Type of y is determined to be an int


5.      py.typed files are now respected when using the “useLibraryCodeForTypes” setting

The “python.analysis.useLibraryCodeForTypes” setting tells Pylance to infer type information from library code even if it does not contain type annotations.

PEP 561 defines a special “py.typed” file that library authors can include in their packages. A “py.typed” file indicates that the code is properly annotated and indicates that type checkers like Pylance should use this type information.

Previously, if the “python.analysis.useLibraryCodeForTypes“ setting was set to false, Pylance ignored the “py.typed” file, leaving all symbols imported from that package with an “unknown” type. With this change, regardless of the setting for “useLibraryCodeForTypes”, Pylance will parse the source files for inline annotations if the “py.typed” file exists.

I hope you find these enhancements useful, and they help you write more Pythonic code. As always, we welcome you to go to our GitHub repo ( and submit your suggestions or issues. We look forward to hearing from you and thank you for your continued support in helping us, the the Python team at Microsoft, deliver the best developer experience for Python development.





Discussion is closed.

Feedback usabilla icon