Pylance: Fix Static Detection Error With LiteralString
Introduction
This article addresses a specific issue encountered in Pylance, a static type checker for Python, where an assignment involving list[LiteralString] and list[str] triggers a reportAssignmentType error. We'll explore the root cause of this error, provide a detailed explanation, and discuss potential solutions to resolve it. Understanding this issue is crucial for developers aiming to leverage the benefits of static type checking while working with literal types in Python. Static type checking can help catch errors early in development, leading to more robust and maintainable code. This article will guide you through the intricacies of type compatibility between LiteralString and str in the context of Python lists, ensuring you can effectively use Pylance to its full potential.
Environment
- Pylance version: ms-python.vscode-pylance 2025.9.1
- OS and version: Windows 10
- Python version: 3.13.8
Problem Description
The core problem lies in the incompatibility between list[LiteralString] and list[str] during static type checking in Pylance. Specifically, when you attempt to assign a list of LiteralString type to a list of str type, Pylance raises a reportAssignmentType error. This behavior stems from the strict type variance rules enforced by static type checkers like Pylance, which aim to ensure type safety and prevent unexpected runtime errors. In essence, Pylance flags this assignment as potentially unsafe because a LiteralString is a more specific type than a general str, and assigning a list of specific strings to a list that expects any string could lead to issues if the code later expects to add arbitrary strings to the list. Let’s delve deeper into the reasons behind this behavior and how to address it effectively.
Code Snippet
from typing import LiteralString
a: list[LiteralString] = ["123"]
b: list[str] = a
Expected Behavior
The expectation is that the static detection should pass without any errors. Ideally, Pylance should recognize that a list[LiteralString] can be safely treated as a list[str] since every LiteralString is indeed a str. This would align with a more flexible interpretation of type compatibility, where a more specific type can be used in place of a more general type. However, due to the strictness of static type checking, this expectation is not met in this particular scenario. Understanding why this expectation isn't met is key to finding appropriate workarounds and solutions.
Actual Behavior
Pylance raises a reportAssignmentType error, indicating that the type list[LiteralString] cannot be assigned to the declared type list[str]. The error message further explains that the type parameter _T@list is invariant, meaning that LiteralString and str are treated as distinct types, preventing the assignment. The suggestion to switch from list to Sequence (covariant) hints at a potential solution by leveraging a more flexible type that allows for subtype relationships. This error message is crucial in understanding the underlying type incompatibility and guiding the developer toward appropriate remedies.
[
{
"owner": "Pylance",
"code": {
"value": "reportAssignmentType",
"target": {
"$mid": 1,
"external": "https://github.com/microsoft/pylance-release/blob/main/docs/diagnostics/reportAssignmentType.md",
"path": "/microsoft/pylance-release/blob/main/docs/diagnostics/reportAssignmentType.md",
"scheme": "https",
"authority": "github.com"
}
},
"severity": 8,
"message": "Type \"list[LiteralString]\" is not assignable to type \"list[str]\"\n Type \"list[LiteralString]\" is not assignable to type \"list[str]\"\n Type argument \"_T@list\" is invariant, but \"LiteralString\" and \"str\" could be distinct\n Consider changing \"list\" to \"Sequence\" (covariant)",
"source": "Pylance",
"startLineNumber": 9,
"startColumn": 16,
"endLineNumber": 9,
"endColumn": 17,
"origin": "extHost1"
}
]
Explanation of the Issue
The error arises due to the variance of list in Python's type system. list is invariant, which means that list[LiteralString] is not considered a subtype of list[str], even though LiteralString is a subtype of str. This is because a list[str] can accept any string, while a list[LiteralString] can only accept specific literal strings. Assigning a list[LiteralString] to a list[str] could lead to runtime errors if the code later attempts to add non-LiteralString values to the list. Pylance, being a static type checker, flags this potential type violation. The concept of variance is central to understanding type compatibility in statically typed languages. Covariance, contravariance, and invariance dictate how type relationships are preserved or transformed when dealing with parameterized types like lists and other generic collections. In this particular case, the invariance of lists is the key factor causing the reportAssignmentType error.
Solutions and Workarounds
Several approaches can be taken to address this issue:
-
Use
Sequenceinstead oflist:Sequenceis a covariant type, meaning thatSequence[LiteralString]is considered a subtype ofSequence[str]. This allows the assignment to pass static type checking.from typing import LiteralString, Sequence a: Sequence[LiteralString] = ["123"] b: Sequence[str] = a -
Explicitly cast the list: You can use
typing.castto explicitly tell the type checker that the assignment is safe.from typing import LiteralString, cast a: list[LiteralString] = ["123"] b: list[str] = cast(list[str], a)While this resolves the error, it bypasses the type checker's safety mechanism, so use it with caution and only when you are confident that the assignment is indeed safe.
-
Create a new list: Create a new
list[str]from thelist[LiteralString]. This ensures that the new list is explicitly of the correct type.from typing import LiteralString a: list[LiteralString] = ["123"] b: list[str] = list(a)This approach creates a copy of the original list, which might have performance implications if the list is large.
-
Ignore the error: If you are certain that the assignment is safe and the type checker is being overly strict, you can use
# type: ignoreto suppress the error.from typing import LiteralString a: list[LiteralString] = ["123"] b: list[str] = a # type: ignoreHowever, this should be used as a last resort, as it disables type checking for that specific line and may hide potential issues.
Choosing the right solution depends on the specific context and requirements of your code. If you need to preserve the original type of the list and avoid creating a copy, using Sequence might be the most appropriate option. If you are confident in the safety of the assignment and want to avoid modifying the code, using typing.cast or # type: ignore might be acceptable. However, it's generally recommended to prefer solutions that maintain type safety and avoid bypassing the type checker whenever possible.
Conclusion
The reportAssignmentType error encountered when assigning a list[LiteralString] to a list[str] in Pylance highlights the importance of understanding type variance in Python's type system. By using Sequence instead of list, explicitly casting the list, creating a new list, or (as a last resort) ignoring the error, you can effectively address this issue and ensure that your code passes static type checking. Always strive for solutions that maintain type safety and minimize the need to bypass the type checker. This ensures that your code remains robust and maintainable. Understanding these nuances can significantly improve your ability to write cleaner, more reliable Python code with the help of static analysis tools like Pylance.
For more information on type variance and static type checking, refer to the official Python documentation and resources on mypy and Pylance.