FWIW, pyright currently uses the following heuristics to distinguish an implicit (inferred) type alias definitions from a regular variable assignment. A type alias is inferred if all of the following conditions apply: 1. There is no type annotation provided 2. There is only one assignment to the symbol 3. The expression on the RHS of the assignment does not contain any syntactic form that would be considered illegal for a type annotation (call expressions, lambdas, comprehensions, etc.) 4. The type evaluation of the RHS evaluates to an instantiable type or a union of instantiable types The current heuristics don't require that the symbol is in the global (module-level) scope. Points #1 and #2 generally distinguish class variables from class-scoped type aliases in the vast majority of cases. Even if these heuristics fail and incorrectly identify a class variable as a type alias, it tends to work fine (no false positive errors). I don't recall ever receiving a bug report or a question about this, so it seems to work well. I do agree that it would be beneficial to standardize this behavior across type checkers. I know that some pyright users rely on our current behavior, so there could be some pain if we were to change it, but (depending on what we conclude here) there's likely a straightforward workaround we can offer the affected users. -- Eric Traut Contributor to Pyright & Pylance Microsoft