mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-03 19:37:39 +03:00
Deleted redundant documentation.
This commit is contained in:
parent
c8e4d9c5d7
commit
5ca3d900fd
@ -35,77 +35,3 @@ The [binder](https://github.com/microsoft/pyright/blob/main/packages/pyright-int
|
||||
|
||||
The [checker](https://github.com/microsoft/pyright/blob/main/packages/pyright-internal/src/analyzer/checker.ts) is responsible for checking all of the statements and expressions within a source file. It relies heavily on the [typeEvaluator](https://github.com/microsoft/pyright/blob/main/packages/pyright-internal/src/analyzer/typeEvaluator.ts) module, which performs most of the heavy lifting. The checker doesn’t run on all files, only those that require full diagnostic output. For example, if a source file is not part of the program but is imported by the program, the checker doesn’t need to run on it.
|
||||
|
||||
## Type Checking Concepts
|
||||
|
||||
Pyright uses an internal type called “Unknown” to represent types that are not annotated and cannot be inferred. Unknown is generally treated like the “Any” type in terms of type checking, but it provides a way for developers to know when type annotations are missing and could provide additional value.
|
||||
|
||||
Pyright attempts to infer the types of global (module-level) variables, class variables, instance variables, and local variables. Return and yield types are also inferred. If type annotations are provided in these cases, the type annotation overrides any inferred types.
|
||||
|
||||
Pyright supports type narrowing to track assumptions that apply within certain code flow paths. For example, consider the following code:
|
||||
```python
|
||||
def func(a: str | list[str] | None):
|
||||
if isinstance(a, str):
|
||||
log(a)
|
||||
elif isinstance(a, list):
|
||||
log(msg) for msg in a
|
||||
else:
|
||||
log(a)
|
||||
```
|
||||
|
||||
In this example, the type evaluator knows that parameter a is either None, str, or list[str]. Within the first `if` clause, a is constrained to be a str. Within the `elif` clause, it is constrained to be a list[str], and within the `else` clause, it has to be None (by process of elimination). The type checker would therefore flag the final line as an error if the log method could not accept None as a parameter.
|
||||
|
||||
Narrowing is also applied when values are assigned to a variable.
|
||||
|
||||
```python
|
||||
def func(b: str | list[str] | None):
|
||||
# The declared type of “a” is a union of three types
|
||||
# (str, list[str] and None).
|
||||
a: str | list[str] | None = b
|
||||
reveal_type(a) # Type is `str | list[str] | None`
|
||||
|
||||
a = "hi"
|
||||
reveal_type(a) # Type is `str`
|
||||
|
||||
a = ["a", "b", "c"]
|
||||
reveal_type(a) # Type is `list[str]`
|
||||
|
||||
a = None
|
||||
reveal_type(a) # Type is `None`
|
||||
```
|
||||
|
||||
If the type narrowing logic exhausts all possible subtypes, it can be assumed that a code path will never be taken. For example, consider the following:
|
||||
|
||||
```python
|
||||
def func(a: Foo | Bar):
|
||||
if isinstance(a, Foo):
|
||||
# “a” must be type Foo
|
||||
a.do_something_1()
|
||||
elif isinstance(a, Bar):
|
||||
# “a” must be type Bar
|
||||
a.do_something_2()
|
||||
else:
|
||||
# This code is unreachable, so type of “a” is "Never"
|
||||
a.do_something_3()
|
||||
```
|
||||
|
||||
In this case, the type of parameter “a” is initially “Union[Foo, Bar]”. Within the “if” clause, the type narrowing logic will conclude that it must be of type “Foo”. Within the “elif” clause, it must be of type “Bar”. What type is it within the “else” clause? The type narrowing system has eliminated all possible subtypes, so it gives it the type “Never”. This is generally indicates that there’s a logic error in the code because there’s way that code block will ever be executed.
|
||||
|
||||
Narrowing is also used to discriminate between subtypes of a union when the union subtypes have a common member with declared literal types that differentiate between the subtypes.
|
||||
|
||||
```python
|
||||
class Foo:
|
||||
kind: Literal["Foo"]
|
||||
def do_something_1(self):
|
||||
pass
|
||||
|
||||
class Bar:
|
||||
kind: Literal["Bar"]
|
||||
def do_something_2(self):
|
||||
pass
|
||||
|
||||
def func(a: Foo | Bar):
|
||||
if a.kind == "Foo":
|
||||
a.do_something_1()
|
||||
else:
|
||||
a.do_something_2()
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user