Aqui está o código
# args: argparse.Namespace
source: str = args.source
...
# subparsers: argparse._SubParsersAction
parser = subparsers.add_parser()
Na primeira linha de código, : str
basta dizer ao Pylance que source
é uma string, embora args.source
seja Any
.
Entretanto, na segunda linha, quando adiciono : argparse.ArgumentParser
, o tipo de parser
ainda é Any | argparse.ArgumentParser
. Tenho que usar manualmente cast(argparse.ArgumentParser)
para obter o efeito desejado, já que add_parser()
é digitado como returing Any
.
Por que isso acontece? Ambas são atribuições para mim, uma de um campo, outra do retorno de uma função.
No esquema
LEFT = RIGHT
, seRIGHT
não for atribuível aLEFT
, então ele "precisa de umcast
"*.Isso também se aplica ao tipo de retorno de uma função, da seguinte forma:
Alguns exemplos gerais:
RIGHT
é um subtipo deLEFT
- não precisa decast
:RIGHT
é um supertipo deLEFT
- precisa decast
:LEFT
- também precisa decast
:Quanto aos seus exemplos na pergunta:
Any
é tratado de forma especial no sistema de tipos. Da especificação de tipagem :Isso permite o seguinte sem
cast
:Na verdade, isso é apenas uma peculiaridade do pyright/pylance. Quando o pyright pensa que você está fazendo algo errado em
RIGHT
, ele propaga um tipoAny
(ou, na terminologia do próprio pyright,Unknown
) para ,LEFT
mesmo queLEFT
já tenha uma anotação explícita (outros verificadores de tipo podem não fazer isso). Aqui está um reprodutor simples:Quanto ao motivo pelo qual os direitos autorais acham que você está fazendo algo errado, há três problemas com seu snippet:
subparsers: argparse._SubParsersAction
Não é atribuído um valor; é apenas uma declaração. O Pyright detesta isso e pode até se recusar a ler quaisquer anotações.subparsers: argparse._SubParsersAction
Falta um argumento de tipo na sua declaração de . Dos stubs da biblioteca padrão :Você não deve usar esta anotação (ela é prefixada com um sublinhado); um trecho de código bem escrito e totalmente tipado usando ,
argparse
nunca deve precisar usar anotações privadas deargparse
, pois todos os tipos podem ser inferidos. No entanto, se você realmente quiser usar esta anotação, precisará fornecer um tipo concreto que seja limitado aargparse.ArgumentParser
, comosubparsers: argparse._SubParsersAction[argparse.ArgumentParser] = parser.add_subparsers(...)
. Este argumento de tipo é, na verdade, usado para resolver o tipo de retorno doadd_parser
método , portanto, se você omiti-lo, o tipo de retorno será insolúvel.Sua chamada de "of"
add_parser
está sem o primeiro argumento obrigatórioname
. Novamente, o autor da frase não gosta disso e propaga umUnknown
"to"LEFT
se a sua expressão de chamada estiver errada:* É claro que, em algumas situações, você não "precisa de uma conversão" — uma anotação de tipo explícita junto com um
# type: ignore
or# pyright: ignore[<some error code>]
funcionará perfeitamente, além de ativarreportUnnecessaryTypeIgnoreComment
o aviso para comentários de ignorar desnecessários. Isso evita a necessidade de uma consulta extra a variáveis de tempo de execução e uma chamada paratyping.cast
.