Anotações de tipo
Tipos opcionais em variáveis, parâmetros e retorno — verificados em execução e por análise estática.
A forma#
idade: Integer := 30 # variável
action media(nums: Cluster) -> Float: # parâmetro e retorno
yield sum(nums) / len(nums)
lambda (n: Integer): n + 1 # lambda (exige parênteses)Anotar é opcional. O código funciona sem, mas quando presente a anotação é verificada — pelo interpretador e pelo `dataforge check`.
O que é verificado#
- O valor atribuído a uma variável anotada
- Cada argumento passado a um parâmetro anotado, na fronteira da ação
- O valor devolvido pelo
yield, contra o tipo declarado - Se uma ação com retorno declarado pode terminar sem
yield(aviso)
Por que na fronteira#
Compare as duas formas de errar:
TypeError_: unsupported operand type(s) for *: 'str' and 'int'
parameter 'largura' of action 'area' declared as Number but got StringA segunda diz onde e o quê. É por isso que a checagem acontece na entrada da ação, e não lá dentro quando a conta explode.
Os nomes aceitos#
| Canônico | Sinônimos | Aceita |
|---|---|---|
Integer | integer, int | inteiros |
Float | float | decimais e inteiros |
Number | number | inteiros ou decimais |
String | string, str, text | textos |
Boolean | boolean, bool | yes / no |
Cluster | cluster, list, array | listas |
Vault | vault, dict, map | dicionários |
Void | void, none | apenas void |
Action | action, function | ações e lambdas |
Stream | stream | o retorno de um stream action |
Any | any | tudo — desliga a checagem |
Qualquer outro nome é tratado como record, enum ou blueprint, e a checagem percorre a cadeia de herança.
A regra de alargamento#
media: Float := 8 # ok — todo inteiro é um decimal válido
quantidade: Integer := 3.5 # erro — 3.5 não é inteiroUm Integer entra onde se espera Float. O contrário perderia informação, e por isso é recusado. Essa é a única flexibilização do sistema.
Coleções: o recipiente, não o conteúdo#
notas: Cluster := [7.5, 8.0] # "é uma lista" — nada diz sobre os itensDataForge 4.0 ainda não tem Cluster<Float> — generics estão no roadmap. Enquanto isso, o conteúdo se valida com código:
action todos_numeros(valores: Cluster) -> Boolean:
cycle v in valores:
given typeof(v) isnt "Integer" and typeof(v) isnt "Float":
yield no
yield yesRecords: campos sempre tipados#
Diferente de variáveis e parâmetros, o tipo de um campo de record é obrigatório:
record Usuario:
nome: String
idade: Integer
email: String := "sem@email" # com valor padrãoA checagem estática#
O dataforge check encontra os mesmos problemas antes de executar, com sugestão de correção:
app.df:14:1: erro: Declared as String but the value is Integer
sugestão: Change the annotation to Integer or fix the value
app.df:13:1: erro: Unknown type 'Intger'
sugestão: Did you mean 'Integer'?Detalhes em Análise estática.