
Passo 1 de 7
Um tipo para cada chave
Reconheça quando um dicionário armazena valores de um mesmo tipo e quando ele representa um registro com campos conhecidos e contratos próprios.
Trilha de aprendizado · Nível 12 · Tutorial 10
Representar dicionários com campos conhecidos e tipos específicos por chave, distinguindo campos ausentes de campos cujo valor pode ser None.
Um tipo para cada chave
Reconheça quando um dicionário armazena valores de um mesmo tipo e quando ele representa um registro com campos conhecidos e contratos próprios. 2 min
Declarar um registro com campos obrigatórios
Declare um TypedDict pela sintaxe de classe e construa um registro de tarefa compatível. 3 min
Consultar e atualizar campos com precisão
Use chaves literais para preservar o tipo de cada campo de um TypedDict ao consultar, atualizar e passar registros para funções. 3 min
Separar ausência de chave e valor None
Modele separadamente se uma chave precisa existir e se seu valor pode ser None. 3 min
Interpretar e corrigir diagnósticos do mypy
Use os diagnósticos do mypy para localizar incompatibilidades em registros TypedDict e corrigir o código sem enfraquecer seu contrato. 3 min
Reconhecer os limites em tempo de execução
Distingua o contrato estático de TypedDict do comportamento real de dicionários durante a execução. 2 min
Aplicação final: modelar e usar um registro
Integre TypedDict, NotRequired, valores None, consultas, atualizações e verificação com mypy em um pequeno programa local. 3 min

Passo 1 de 7
Reconheça quando um dicionário armazena valores de um mesmo tipo e quando ele representa um registro com campos conhecidos e contratos próprios.
Considere os dados de uma tarefa: ela tem um título, uma prioridade e a quantidade estimada de minutos.
{"titulo": "Revisar proposta", "prioridade": 2, "minutos_estimados": 30}Aqui, as chaves têm papéis conhecidos. titulo deve guardar texto, enquanto prioridade e minutos_estimados devem guardar inteiros. Esse uso de dicionário é um registro: um conjunto de campos nomeados, cada qual com seu próprio contrato.
Observe que o tipo esperado depende da chave consultada.

Em um registro, o nome do campo determina o tipo esperado para seu valor.
Você poderia anotar esses dados assim:
tarefa: dict[str, str | int] = {
"titulo": "Revisar proposta",
"prioridade": 2,
"minutos_estimados": 30,
}Essa anotação informa que qualquer valor do dicionário pode ser str ou int. Ela não expressa que titulo é especificamente str, nem que prioridade é especificamente int.
Portanto, dict[str, str | int] é útil quando todas as chaves seguem o mesmo contrato de valores possíveis, mas perde a relação entre cada nome de campo e seu tipo próprio.
Compare as informações descritas por cada anotação.
# Mesmo contrato para todos os valores:
tarefa_generica: dict[str, str | int]
# Contrato desejado para um registro:
# "titulo" -> str
# "prioridade" -> int
# "minutos_estimados" -> int
#
# TypedDict permite descrever essa relação por chave.TypedDict é um recurso de tipagem para descrever dicionários que funcionam como registros. Ele permite declarar, estaticamente, quais chaves são conhecidas e qual tipo pertence a cada uma.
Assim, em vez de dizer apenas “os valores podem ser texto ou inteiro”, você pode representar o contrato preciso: titulo corresponde a texto; prioridade e minutos_estimados, a inteiros.
Nos próximos passos, você vai escrever essa declaração e usar o contrato ao consultar e atualizar os campos.
A diferença central é onde está o contrato de tipo.

dict[str, str | int] repete um contrato para todas as chaves; TypedDict associa um contrato a cada campo.
Associe cada situação ao contrato mais adequado.
Toque em um item e depois no par correspondente.

Passo 2 de 7
Declare um TypedDict pela sintaxe de classe e construa um registro de tarefa compatível.
Com Python 3.12 ou superior, importe TypedDict de typing. Em seguida, declare uma classe cujos atributos anotados representam as chaves e os tipos dos valores de um registro.
No TypedDict pela sintaxe de classe, todos os campos são obrigatórios por padrão.
from typing import TypedDict
class Tarefa(TypedDict):
titulo: str
prioridade: int
concluida: bool
Cada nome de campo possui seu próprio tipo de valor.
Use o nome do TypedDict na anotação da variável e atribua um literal de dicionário. Para ser compatível, o literal precisa incluir titulo, prioridade e concluida, com os tipos definidos no contrato.
tarefa: Tarefa = {
"titulo": "Enviar relatório",
"prioridade": 2,
"concluida": False,
}Dica
Tarefa descreve o formato esperado pelo verificador de tipos. Os nomes das chaves no literal devem corresponder aos campos declarados, e cada valor deve respeitar o tipo daquele campo.
Considere a classe Tarefa(TypedDict) já declarada. Complete a lacuna:nova_tarefa: ____ = {"titulo": "Estudar", "prioridade": 1, "concluida": False}

Passo 3 de 7
Use chaves literais para preservar o tipo de cada campo de um TypedDict ao consultar, atualizar e passar registros para funções.
Considere o registro Tarefa já declarado com titulo: str, prioridade: int e concluida: bool. Ao acessar uma chave literal conhecida, o mypy usa o tipo declarado especificamente para aquela chave — não uma união de todos os tipos do registro.
A mesma estrutura oferece resultados de tipos diferentes conforme a chave consultada.

A chave literal determina o tipo que o verificador associa ao valor acessado.
Cada expressão entre colchetes tem seu tipo próprio.
tarefa: Tarefa = {
"titulo": "Revisar proposta",
"prioridade": 2,
"concluida": False,
}
quantidade_caracteres = len(tarefa["titulo"]) # str
proxima_prioridade = tarefa["prioridade"] + 1 # int
if not tarefa["concluida"]: # bool
print(tarefa["titulo"])Na atualização por colchetes, o novo valor deve ser compatível com o tipo da chave escolhida. Assim, tarefa["prioridade"] = 3 mantém o contrato; já atribuir um texto a essa chave viola o tipo declarado.
O tipo esperado depende da chave à esquerda da atribuição.
tarefa["titulo"] = "Enviar proposta"
tarefa["prioridade"] = 3
tarefa["concluida"] = True
# Incompatível com o contrato de Tarefa:
# tarefa["prioridade"] = "alta"Dica
Não trate o registro como se todos os valores tivessem o tipo str | int | bool. Em um TypedDict, cada nome de campo conhecido leva ao seu contrato específico.
Ao receber Tarefa como parâmetro, a função conserva as informações de cada campo. Isso permite usar operações de texto em titulo, cálculos em prioridade e condições em concluida.
A anotação evita que o parâmetro seja visto apenas como um dicionário de valores mistos.
def resumo(tarefa: Tarefa) -> str:
estado = "concluída" if tarefa["concluida"] else "pendente"
nivel = tarefa["prioridade"] + 1
return f"{tarefa['titulo']} — {estado} (nível {nivel})"
print(resumo(tarefa))Para uma variável tarefa: Tarefa com titulo: str, prioridade: int e concluida: bool, qual expressão respeita o contrato?

Passo 4 de 7
Modele separadamente se uma chave precisa existir e se seu valor pode ser None.
Ao descrever um campo, responda a duas perguntas separadas:
None?NotRequired[...] responde à primeira pergunta: a chave pode faltar. Já T | None responde à segunda: a chave existe, mas pode guardar None.
Por padrão, um campo declarado em um TypedDict continua obrigatório.
As quatro combinações possíveis para um campo de registro.

A obrigatoriedade da chave e a aceitação de None são propriedades independentes.
Python 3.12+
from typing import NotRequired, TypedDict
class Tarefa(TypedDict):
titulo: str
responsavel: str | None
prazo: NotRequired[str]
observacao: NotRequired[str | None]
com_responsavel_desconhecido: Tarefa = {
"titulo": "Revisar relatório",
"responsavel": None,
}
sem_prazo: Tarefa = {
"titulo": "Enviar proposta",
"responsavel": "Lia",
}
com_observacao_nula: Tarefa = {
"titulo": "Organizar reunião",
"responsavel": "Caio",
"observacao": None,
}responsavel: str | None: a chave é obrigatória; seu valor pode ser texto ou None.prazo: NotRequired[str]: a chave pode estar ausente; se existir, seu valor deve ser texto.observacao: NotRequired[str | None]: a chave pode estar ausente; se existir, aceita texto ou None.Em sem_prazo, a chave prazo não foi criada. NotRequired não insere a chave e não produz valor padrão.
Atenção
tarefa["prazo"] pode lançar KeyError se prazo estiver ausente. O mypy pode aceitar esse acesso por conhecer o tipo do valor quando a chave existe, mas isso não garante sua presença em tempo de execução.
Verifique presença antes de usar um campo NotRequired.
def descrever_observacao(tarefa: Tarefa) -> str:
if "observacao" not in tarefa:
return "Sem observação registrada"
observacao = tarefa["observacao"]
if observacao is None:
return "Observação ainda não definida"
return observacao.upper()Dica
Para NotRequired[str | None], faça dois testes quando precisar usar uma operação de str: primeiro, "campo" in registro; depois, registro["campo"] is not None — diretamente ou guardando o valor em uma variável, como no exemplo.
Associe cada requisito de campo à declaração apropriada.
Toque em um item e depois no par correspondente.
Para chamar .upper() em tarefa["observacao"], sendo observacao: NotRequired[str | None], o que o código deve garantir antes?

Passo 5 de 7
Use os diagnósticos do mypy para localizar incompatibilidades em registros TypedDict e corrigir o código sem enfraquecer seu contrato.
Quando o mypy encontra um problema em um TypedDict, ele indica a linha e o contrato que não foi cumprido. Os casos mais comuns são: campo obrigatório ausente, valor com tipo incompatível, chave que não existe no registro e atualização com valor do tipo errado.
O diagnóstico não é um convite para usar Any ou ignorá-lo: ele mostra onde o código deixou de representar o contrato declarado.
Cada marcação corresponde a uma regra específica do registro.

Localize primeiro a chave e a operação citadas pelo mypy; depois ajuste o dado para que corresponda ao TypedDict.
Crie um arquivo chamado diagnosticos_tarefa.py com este conteúdo. As linhas com comentários ERRO foram deixadas incorretas de propósito.
from typing import NotRequired, TypedDict
class Tarefa(TypedDict):
titulo: str
prioridade: int
prazo: NotRequired[str | None]
incompleta: Tarefa = {"titulo": "Estudar TypedDict"} # ERRO: falta prioridade
valor_invalido: Tarefa = {"titulo": "Estudar", "prioridade": "alta"} # ERRO
chave_extra: Tarefa = {
"titulo": "Estudar",
"prioridade": 2,
"etiqueta": "python", # ERRO: chave não declarada
}
print(chave_extra["etiqueta"]) # ERRO: consulta uma chave desconhecida
correta: Tarefa = {"titulo": "Estudar", "prioridade": 2}
correta["prioridade"] = "urgente" # ERRO: prioridade aceita int
No terminal, na pasta do arquivo, execute:
python -m mypy --python-version 3.12 diagnosticos_tarefa.py
Você deve encontrar categorias de diagnóstico equivalentes a estas (a redação exata pode variar conforme a versão):
prioridade ausente;str incompatível com o item prioridade, que espera int;etiqueta no literal de Tarefa;Tarefa não possui a chave etiqueta;str incompatível para prioridade.Em seguida, substitua todo o conteúdo do arquivo pela versão corrigida abaixo e execute o mesmo comando novamente.
A correção adiciona o campo exigido, usa valores compatíveis, remove a chave não declarada, consulta uma chave conhecida e atualiza prioridade com um inteiro.
from typing import NotRequired, TypedDict
class Tarefa(TypedDict):
titulo: str
prioridade: int
prazo: NotRequired[str | None]
incompleta: Tarefa = {
"titulo": "Estudar TypedDict",
"prioridade": 1,
}
valor_valido: Tarefa = {"titulo": "Estudar", "prioridade": 2}
sem_chave_extra: Tarefa = {
"titulo": "Estudar",
"prioridade": 2,
}
print(sem_chave_extra["titulo"])
correta: Tarefa = {"titulo": "Estudar", "prioridade": 2}
correta["prioridade"] = 3
Após executar as duas versões, relate quais diagnósticos apareceram na primeira e qual alteração resolveu cada um. Inclua o resultado final do mypy em suas palavras.
Escreva pelo menos 180 caracteres (0/180).

Passo 6 de 7
Distingua o contrato estático de TypedDict do comportamento real de dicionários durante a execução.
Um TypedDict descreve para o mypy quais chaves e tipos um registro deve ter. Em tempo de execução, porém, o valor continua sendo um dict comum: a declaração por classe não cria uma instância que fiscaliza campos automaticamente.
Compare quem analisa o contrato e quem executa o programa.

O mypy pode apontar incompatibilidades antes da execução; o interpretador não aplica o contrato de TypedDict.
Salve como limite_typed_dict.py. Primeiro, rode o mypy; depois, execute o arquivo com Python.
from typing import TypedDict
class Tarefa(TypedDict):
titulo: str
prioridade: int
# O mypy deve diagnosticar: prioridade deveria ser int.
tarefa: Tarefa = {"titulo": "Revisar contrato", "prioridade": "alta"}
print(tarefa)
print(type(tarefa))Com python -m mypy limite_typed_dict.py, o mypy informa que o valor de prioridade é incompatível. Ainda assim, python limite_typed_dict.py cria e exibe o dicionário, inclusive mostrando <class 'dict'>. Executar sem erro não prova que os dados obedecem ao TypedDict.
Atenção
Anotar um valor vindo de fora como Tarefa não confere suas chaves, não converte valores e não impede conteúdo incompatível em tempo de execução. No próximo tutorial, você verá como estabelecer uma fronteira de validação para dados externos.
Se um programa com um registro anotado como TypedDict executa sem erro, então o Python confirmou automaticamente que todas as chaves e valores obedecem ao contrato.

Passo 7 de 7
Integre TypedDict, NotRequired, valores None, consultas, atualizações e verificação com mypy em um pequeno programa local.
Modele uma tarefa com estes campos:
titulo: texto obrigatório;concluida: booleano obrigatório;responsavel: texto ou None, mas a chave é obrigatória;prioridade: inteiro que pode ficar ausente.A presença da chave e o tipo de seu valor são decisões independentes. Portanto, responsavel usa str | None, enquanto prioridade usa NotRequired[int].

Cada campo combina duas informações: se a chave precisa existir e qual tipo de valor ela aceita.
No seu editor, crie um arquivo chamado tarefas.py com o código abaixo. Em um terminal na mesma pasta, execute primeiro python -m mypy tarefas.py e depois python tarefas.py.
Observe separadamente: o mypy confere o contrato anotado; o interpretador executa as operações normais do dicionário.
from typing import NotRequired, TypedDict
class Tarefa(TypedDict):
titulo: str
concluida: bool
responsavel: str | None
prioridade: NotRequired[int]
def descrever(tarefa: Tarefa) -> str:
estado = "concluída" if tarefa["concluida"] else "pendente"
if tarefa["responsavel"] is None:
pessoa = "sem responsável"
else:
pessoa = f"responsável: {tarefa['responsavel']}"
if "prioridade" in tarefa:
prioridade = f"prioridade {tarefa['prioridade']}"
else:
prioridade = "sem prioridade"
return f"{tarefa['titulo']}: {estado}; {pessoa}; {prioridade}"
tarefa: Tarefa = {
"titulo": "Revisar contrato",
"concluida": False,
"responsavel": None,
}
tarefa["prioridade"] = 2
tarefa["concluida"] = True
print(descrever(tarefa))Exemplo
O mypy deve terminar sem erros para esse arquivo. A execução deve exibir uma descrição equivalente a:
Revisar contrato: concluída; sem responsável; prioridade 2
Agora adapte apenas os valores do literal inicial: mantenha as quatro regras do contrato e experimente omitir ou incluir prioridade.
Depois de executar sua versão, relate: (1) a declaração de Tarefa; (2) uma consulta ou atualização compatível que você fez; e (3) por que um resultado sem diagnósticos do mypy não transforma dados externos em dados validados.
Escreva pelo menos 140 caracteres (0/140).
Resumo
TypedDict quando um dicionário representa um registro com chaves conhecidas e tipos específicos por campo.NotRequired.T | None permite o valor None; não torna a chave opcional.TypedDict é um dict comum e não recebe validação automática.Parabéns! Você concluiu: Descrever registros com TypedDict
Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks