<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Isaac Muniz</title>
    <description>The latest articles on Forem by Isaac Muniz (@imuniz).</description>
    <link>https://forem.com/imuniz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2215659%2Ffc3e7d52-f9a1-438c-addd-78b1491bd850.jpg</url>
      <title>Forem: Isaac Muniz</title>
      <link>https://forem.com/imuniz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/imuniz"/>
    <language>en</language>
    <item>
      <title>Sistemas de Tipos: os três eixos que definem como uma linguagem se comporta</title>
      <dc:creator>Isaac Muniz</dc:creator>
      <pubDate>Sat, 02 May 2026 16:38:53 +0000</pubDate>
      <link>https://forem.com/imuniz/sistemas-de-tipos-os-tres-eixos-que-definem-como-uma-linguagem-se-comporta-1na6</link>
      <guid>https://forem.com/imuniz/sistemas-de-tipos-os-tres-eixos-que-definem-como-uma-linguagem-se-comporta-1na6</guid>
      <description>&lt;p&gt;Todo dado em um programa tem um tipo. Um número inteiro, um texto, um valor verdadeiro ou falso - cada um desses é um tipo diferente, e a linguagem precisa saber com qual está lidando para executar operações sobre ele corretamente.&lt;br&gt;
Mas o que acontece quando você tenta somar um número com um texto? Ou usar um objeto onde se espera outro? É aí que entram os sistemas de tipos: o conjunto de regras que cada linguagem define para lidar com essas situações. Diferentes linguagens fazem escolhas muito diferentes nesse sentido, e entender essas escolhas é essencial para qualquer desenvolvedor.&lt;/p&gt;

&lt;p&gt;Para entender essas diferenças, precisamos primeiro responder uma pergunta mais fundamental: o que é exatamente um tipo?&lt;/p&gt;
&lt;h2&gt;
  
  
  Mas afinal, o que é um tipo?
&lt;/h2&gt;

&lt;p&gt;Um tipo define duas coisas: quais valores são válidos e quais operações podem ser realizadas sobre eles. Quando você cria uma variável do tipo &lt;code&gt;number&lt;/code&gt;, a linguagem entende que você pode fazer contas com ela. Quando cria uma do tipo &lt;code&gt;string&lt;/code&gt;, a linguagem sabe que você pode concatenar, dividir em partes, converter para maiúsculas.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tipos Primitivos e Tipos Compostos
&lt;/h3&gt;

&lt;p&gt;Existem dois grandes grupos de tipos: os primitivos e os compostos.&lt;/p&gt;
&lt;h4&gt;
  
  
  Tipos Primitivos
&lt;/h4&gt;

&lt;p&gt;Tipos primitivos são os blocos de construção elementares. Toda linguagem tem algo parecido com isto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TypeScript&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;idade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Isaac&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ativo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Python
&lt;/span&gt;&lt;span class="n"&gt;idade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;    &lt;span class="c1"&gt;# int
&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Isaac&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;    &lt;span class="c1"&gt;# str
&lt;/span&gt;&lt;span class="n"&gt;ativo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;    &lt;span class="c1"&gt;# bool
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;idade&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;27&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Isaac"&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ativo&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;São valores simples, indivisíveis. Um número é um número. Uma string é uma sequência de caracteres. Um booleano é verdadeiro ou falso.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tipos compostos
&lt;/h4&gt;

&lt;p&gt;Tipos compostos são construídos a partir de outros tipos - sejam primitivos ou outros compostos. Eles agrupam dados relacionados em uma estrutura única. Aqui é onde as diferenças entre linguagens começam a aparecer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TypeScript&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Pessoa&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;idade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isaac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pessoa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Isaac&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;idade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Python
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pessoa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;idade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idade&lt;/span&gt;

&lt;span class="n"&gt;isaac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pessoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Isaac&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Pessoa&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Nome&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Idade&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;isaac&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Pessoa&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Isaac"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Idade&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;27&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A ideia é a mesma em todas: agrupar dados relacionados sob um único tipo. Mas por que isso importa?&lt;/p&gt;

&lt;p&gt;Porque assim a linguagem consegue garantir certos comportamentos. Se você tem uma função que espera receber uma &lt;code&gt;Pessoa&lt;/code&gt;, a linguagem pode verificar que você está passando realmente uma &lt;code&gt;Pessoa&lt;/code&gt; - não uma string confundida por acaso. E é aqui que as linguagens começam a divergir: cada uma tem regras diferentes sobre o que é ou não permitido. Vamos começar pela diferença mais intuitiva.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como diferentes linguagens tratam a tipagem
&lt;/h2&gt;

&lt;p&gt;Agora que sabemos o que é um tipo, podemos explorar como as linguagens diferem na forma de lidar com eles. Essa diferença aparece em situações concretas do dia a dia: o que acontece quando você passa um valor do tipo errado para uma função? Quando a linguagem detecta o problema? Ela avisa ou simplesmente segue em frente? As respostas variam bastante, e entendê-las ajuda a tomar decisões mais conscientes, tanto na escolha de uma linguagem quanto no uso dela. Vamos aos exemplos.&lt;/p&gt;

&lt;p&gt;Em JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// JavaScript&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;   &lt;span class="c1"&gt;// == "53" - o número foi silenciosamente convertido para string&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;   &lt;span class="c1"&gt;// == 2 - agora a string foi silenciosamente convertida para número&lt;/span&gt;
&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;   &lt;span class="c1"&gt;// "[object Object]" - resultado que não faz sentido&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O resultado muda dependendo do operador, sem nenhum aviso, sem nenhum erro. Por isso nos exemplos está escrito "silenciosamente". A linguagem fez &lt;strong&gt;coerções implícitas&lt;/strong&gt; - converteu os tipos automaticamente para tentar fazer a operação funcionar de qualquer jeito. Isso é &lt;strong&gt;tipagem fraca&lt;/strong&gt;: a linguagem aceita operações entre tipos incompatíveis sem reclamar.&lt;/p&gt;

&lt;p&gt;PHP tem um comportamento semelhante:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PHP&lt;/span&gt;
&lt;span class="s2"&gt;"5"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// == 8 - string convertida para número automaticamente&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHP moderno evoluiu bastante com o suporte a type hints.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;O que são type hints?&lt;/strong&gt;&lt;br&gt;
Type hints são anotações opcionais que você adiciona ao código para indicar explicitamente qual tipo de dado uma variável, parâmetro ou retorno de função deve ter. O nome é sugestivo: são "dicas de tipo". Dependendo da linguagem, elas podem ser verificadas pela própria linguagem, por ferramentas externas como editores e analisadores estáticos, ou por ambos. Em PHP moderno, ficaria assim:&lt;/p&gt;


&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PHP&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;dobrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;PHP moderno, com type hints, melhorou bastante - mas ainda carrega o legado de ser permissivo com coerções. Outras linguagens fizeram a escolha oposta. Veja o que acontece em Python com a mesma tentativa de somar string e número:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Python
&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="c1"&gt;# TypeError: can only concatenate str (not "int") to str
&lt;/span&gt;
&lt;span class="c1"&gt;# Ou seja: "Erro de Tipagem: só é possível concatenar uma string (não um inteiro) à outra string"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A linguagem simplesmente se recusa. Se você quiser concatenar, precisa ser explícito: &lt;code&gt;"5" + str(3)&lt;/code&gt;. Isso é &lt;strong&gt;tipagem forte&lt;/strong&gt;: a linguagem exige que as operações façam sentido entre os tipos envolvidos.&lt;/p&gt;

&lt;p&gt;TypeScript e Go se comportam da mesma forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TypeScript&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cinco&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Erro: Type 'string' is not assignable to type 'number'&lt;/span&gt;

&lt;span class="c1"&gt;// Traduzindo: "Erro: Tipo 'string' não é atribuível a tipo 'número'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cinco"&lt;/span&gt; &lt;span class="c"&gt;// cannot use "cinco" (type string) as type int&lt;/span&gt;

&lt;span class="c"&gt;// Traduzindo: "não é possível usar "cinco" (do tipo string) como tipo inteiro"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Resumindo:&lt;/strong&gt; forte/fraco mede a &lt;strong&gt;tolerância da linguagem à ambiguidade de tipos&lt;/strong&gt;. Linguagens fracas tentam resolver a situação sozinhas, linguagens fortes exigem que você resolva.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Type hints e verificação em cada linguagem
&lt;/h2&gt;

&lt;p&gt;Type hints existem em várias linguagens, mas como cada uma as usa na prática? As diferenças são grandes - vão desde linguagens que verificam tudo antes de executar até linguagens que tratam type hints como puros comentários decorativos.&lt;/p&gt;

&lt;p&gt;Antes de ver uma tabela comparativa, vale entender o que acontece em cada linguagem quando um erro de tipo ocorre num programa real, porque as consequências são muito diferentes dependendo de onde a verificação acontece.&lt;/p&gt;

&lt;p&gt;Nas linguagens que verificam tipos em compilação, como TypeScript, Go e Java, erros de tipo nunca chegam ao usuário. O compilador rejeita o código e o programa simplesmente não é gerado. O desenvolvedor precisa corrigir o problema antes de compilar e portanto antes de publicar qualquer coisa.&lt;/p&gt;

&lt;p&gt;Nas linguagens que verificam em runtime, como PHP, o erro aparece durante a execução. Se não for tratado pelo código, o servidor retorna uma tela de erro para o usuário. Mas o PHP faz isso de duas formas diferentes, dependendo da configuração do arquivo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type hints em PHP, e modo padrão vs modo estrito
&lt;/h3&gt;

&lt;p&gt;No modo padrão, o PHP tenta ser prestativo: antes de reclamar de um tipo errado, ele tenta converter o valor para o tipo esperado. Se conseguir, segue em frente silenciosamente. Só lança um erro quando a conversão é realmente impossível:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PHP&lt;/span&gt;
&lt;span class="nf"&gt;dobrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// PHP converte "5" para 5 silenciosamente - sem erro&lt;/span&gt;
&lt;span class="nf"&gt;dobrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"abc"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// TypeError - impossível converter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse comportamento é conveniente, mas também perigoso - pode esconder bugs em vez de expô-los. Por isso o PHP oferece um modo mais rigoroso. Basta adicionar a linha &lt;code&gt;declare(strict_types=1);&lt;/code&gt; no topo do arquivo para que a linguagem passe a exigir que os tipos batam exatamente, sem nenhuma conversão automática:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PHP&lt;/span&gt;
&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;dobrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// TypeError - mesmo sendo conversível&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  JavaScript
&lt;/h3&gt;

&lt;p&gt;Em JavaScript, o comportamento é o mais permissivo de todos: erros de tipo raramente interrompem o programa. A linguagem tenta resolver a situação por conta própria com coerções, e o que sobra vai para o console do navegador - invisível para o usuário, silencioso para o desenvolvedor desatento.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type hints em Python
&lt;/h3&gt;

&lt;p&gt;Python fica num meio-termo curioso: a linguagem tem tipagem forte - não faz coerções - mas as type hints não causam nenhum erro por si só. Se um valor do tipo errado entrar numa função, Python não vai reclamar das anotações. Vai reclamar somente quando a operação em si falhar, como tentar multiplicar uma string por outra. Nesse caso, lança uma exceção que, se não tratada, retorna um erro 500 para o usuário.&lt;/p&gt;

&lt;p&gt;Para verificação antecipada em Python, existem ferramentas externas que leem as type hints e apontam inconsistências antes da execução. As mais usadas são &lt;strong&gt;mypy&lt;/strong&gt;, a mais tradicional da comunidade, e &lt;strong&gt;pyright&lt;/strong&gt;, criada pela Microsoft. Já o &lt;strong&gt;Pylance&lt;/strong&gt; é uma extensão do VS Code que usa o pyright por baixo dos panos para mostrar os erros diretamente no editor enquanto você digita.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSDoc em JavaScript
&lt;/h3&gt;

&lt;p&gt;JavaScript também tem uma solução para verificação antecipada sem abrir mão de ser JavaScript: o &lt;strong&gt;JSDoc&lt;/strong&gt; combinado com a diretiva &lt;code&gt;// @ts-check&lt;/code&gt;. JSDoc é um padrão de comentários estruturados que permite anotar tipos diretamente em arquivos &lt;code&gt;.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// JavaScript&lt;/span&gt;
&lt;span class="c1"&gt;// @ts-check&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * @param {number} n
 * @returns {number}
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dobrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;dobrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cinco&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// o editor sublinha o erro&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A diretiva &lt;code&gt;// @ts-check&lt;/code&gt; no topo do arquivo instrui o VS Code a verificar o arquivo usando o mesmo mecanismo do TypeScript por baixo dos panos. Você continua escrevendo JavaScript puro, sem mudar a extensão do arquivo, sem compilar nada. Em execução, os comentários são ignorados e nenhuma verificação acontece - só o editor lê e interpreta as anotações.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tabela: Tipagem em diferentes linguagens
&lt;/h2&gt;

&lt;p&gt;Com isso em mente, a tabela abaixo resume como cada linguagem se comporta:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Linguagem&lt;/th&gt;
&lt;th&gt;Quando a verificação acontece&lt;/th&gt;
&lt;th&gt;Quem verifica&lt;/th&gt;
&lt;th&gt;O que acontece num programa rodando quando há erro de tipo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;Não acontece nativamente&lt;/td&gt;
&lt;td&gt;Ferramentas externas (VS Code com &lt;code&gt;// @ts-check&lt;/code&gt; e JSDoc)&lt;/td&gt;
&lt;td&gt;O programa continua rodando com resultado imprevisível; erros aparecem só no console do navegador&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP (modo padrão)&lt;/td&gt;
&lt;td&gt;Em runtime&lt;/td&gt;
&lt;td&gt;A própria linguagem&lt;/td&gt;
&lt;td&gt;Converte o valor silenciosamente e segue em frente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP (modo estrito)&lt;/td&gt;
&lt;td&gt;Em runtime&lt;/td&gt;
&lt;td&gt;A própria linguagem&lt;/td&gt;
&lt;td&gt;Lança &lt;code&gt;TypeError&lt;/code&gt;; se não tratado, o usuário vê uma página de erro 500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Não acontece nativamente&lt;/td&gt;
&lt;td&gt;Ferramentas externas (mypy, pyright, Pylance)&lt;/td&gt;
&lt;td&gt;Lança exceção; se não tratada, o usuário vê uma página de erro 500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td&gt;Em compilação&lt;/td&gt;
&lt;td&gt;O compilador &lt;code&gt;tsc&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Impossível: o código não compila e nunca chega ao usuário&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;Em compilação&lt;/td&gt;
&lt;td&gt;O compilador &lt;code&gt;go&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Impossível: o código não compila e nunca chega ao usuário&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;Em compilação&lt;/td&gt;
&lt;td&gt;O compilador &lt;code&gt;javac&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Impossível: o código não compila e nunca chega ao usuário&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Os três eixos dos sistemas de tipos
&lt;/h2&gt;

&lt;p&gt;Forte e fraca, como falamos acima, é apenas uma das formas de classificar o sistema de tipos de uma linguagem. Existem três eixos independentes, e confundir um com o outro é muito comum:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Eixo&lt;/th&gt;
&lt;th&gt;Pergunta que responde&lt;/th&gt;
&lt;th&gt;Resposta&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Forte / Fraca&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A linguagem aceita operações entre tipos incompatíveis?&lt;/td&gt;
&lt;td&gt;Não aceita: Forte / Aceita: Fraca&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Estática / Dinâmica&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Os tipos são verificados antes ou durante a execução?&lt;/td&gt;
&lt;td&gt;Antes: Estática / Durante: Dinâmica&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nominal / Estrutural&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dois tipos são compatíveis pelo nome ou pela forma?&lt;/td&gt;
&lt;td&gt;Pelo nome: Nominal / Pela forma: Estrutural&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Já vimos o primeiro eixo em detalhes. Vamos relembrá-lo e explorar os outros dois.&lt;/p&gt;

&lt;h3&gt;
  
  
  Forte vs. Fraca: o quanto a linguagem tolera operações entre tipos incompatíveis?
&lt;/h3&gt;

&lt;p&gt;Linguagens com tipagem fraca, como JavaScript e PHP, fazem coerções implícitas para tentar fazer a operação funcionar. Linguagens com tipagem forte, como Python, TypeScript e Go, se recusam e exigem que o código seja explícito.&lt;/p&gt;

&lt;h3&gt;
  
  
  Estática vs. Dinâmica: quando os tipos são verificados?
&lt;/h3&gt;

&lt;p&gt;Linguagens como Go compilam o código antes de rodar: um programa chamado compilador lê o código inteiro, verifica os tipos e só então gera o executável. Se houver um erro de tipo, o programa nem começa a rodar. Isso é &lt;strong&gt;tipagem estática&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Linguagens como Python e JavaScript não têm essa etapa. O código é lido e executado linha a linha, e os tipos só são verificados quando aquela linha específica roda. Um erro de tipo numa função raramente chamada pode passar despercebido por muito tempo - até o dia em que essa função for executada em produção. Isso é &lt;strong&gt;tipagem dinâmica&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TypeScript é um caso especial:&lt;/strong&gt; ele compila, mas não gera código de máquina - gera JavaScript, que depois é interpretado. Mesmo assim, é durante a compilação que os tipos são verificados, por isso é considerado estaticamente tipado.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Uma consequência prática da tipagem dinâmica é que a mesma variável pode receber valores de tipos diferentes ao longo do código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Python
&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;        &lt;span class="c1"&gt;# x aponta para um inteiro
&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# x agora aponta para uma string - sem erro
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso funciona porque em Python o tipo pertence ao valor, não à variável. A variável &lt;code&gt;x&lt;/code&gt; é só um nome que aponta para um valor: primeiro apontava para &lt;code&gt;5&lt;/code&gt; (do tipo &lt;code&gt;int&lt;/code&gt;), depois passou a apontar para &lt;code&gt;"hello"&lt;/code&gt; (do tipo &lt;code&gt;str&lt;/code&gt;). Os valores em si continuam tendo seus tipos - o que mudou foi apenas para qual valor &lt;code&gt;x&lt;/code&gt; está apontando.&lt;/p&gt;

&lt;p&gt;Em linguagens com tipagem estática, como Go, é o oposto: o tipo pertence à variável. Quando você declara &lt;code&gt;var x int&lt;/code&gt;, está dizendo que &lt;code&gt;x&lt;/code&gt; é um recipiente que só aceita inteiros. Ele não pode passar a apontar para uma string, independentemente do que aconteça:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt; &lt;span class="c"&gt;// ❌ cannot use "hello" (type string) as type int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  A escolha entre tipagem estática vs. dinâmica
&lt;/h4&gt;

&lt;p&gt;A escolha entre estática e dinâmica envolve uma troca. Tipagem estática oferece segurança antecipada: erros são detectados antes de o programa rodar, o que é especialmente valioso em projetos grandes. Tipagem dinâmica oferece flexibilidade e agilidade: o código tende a ser mais enxuto e não exige declarações de tipo em todo lugar, o que pode acelerar o desenvolvimento em projetos menores ou exploratórios. Não há uma escolha universalmente certa - depende do contexto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nominal vs. Estrutural: o que torna dois tipos compatíveis?
&lt;/h3&gt;

&lt;p&gt;Esse eixo responde a uma pergunta mais sutil: para a linguagem aceitar que um tipo &lt;code&gt;B&lt;/code&gt; seja usado onde se espera um tipo &lt;code&gt;A&lt;/code&gt;, o que precisa ser verdade?&lt;/p&gt;

&lt;p&gt;Em linguagens com tipagem &lt;strong&gt;nominal&lt;/strong&gt;, o que importa é o nome declarado. Dois tipos são compatíveis somente se houver uma relação explícita entre eles. Java é um exemplo claro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Java&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Au!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se você criar uma classe &lt;code&gt;Cat&lt;/code&gt; com exatamente os mesmos métodos mas sem declarar &lt;code&gt;implements Animal&lt;/code&gt;, o Java não vai aceitar um &lt;code&gt;Cat&lt;/code&gt; onde se espera um &lt;code&gt;Animal&lt;/code&gt; - mesmo que a estrutura seja idêntica:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Java&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cat&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Miau!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Cat cannot be converted to Animal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em linguagens com tipagem &lt;strong&gt;estrutural&lt;/strong&gt;, o que importa é a forma - os métodos e propriedades que o tipo possui. Se a estrutura bate, a operação é aceita, independentemente do nome ou de qualquer declaração explícita. TypeScript funciona assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TypeScript&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Au!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Dog nunca declarou que implementa Animal,&lt;/span&gt;
&lt;span class="c1"&gt;// mas TypeScript aceita porque a estrutura é compatível&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso tem um nome: &lt;strong&gt;duck typing estático&lt;/strong&gt;. A expressão vem de um ditado em inglês: &lt;em&gt;"If it walks like a duck and quacks like a duck, it's a duck"&lt;/em&gt; - "se anda como pato e grasna como pato, é um pato". A identidade de um tipo é definida pelo que ele faz, não pelo que ele se declara ser. O "estático" indica que essa verificação ainda acontece em tempo de compilação.&lt;/p&gt;

&lt;p&gt;Python também é estrutural, mas sem checagem antecipada - qualquer objeto que tenha os métodos certos é aceito, e a linguagem só descobre incompatibilidades em execução. Go mistura as duas abordagens: tipos concretos são nominais, mas interfaces são estruturais, o que significa que uma struct satisfaz uma interface automaticamente, sem precisar declará-la explicitamente.&lt;/p&gt;

&lt;h4&gt;
  
  
  A escolha entre tipagem nominal vs. estrutural
&lt;/h4&gt;

&lt;p&gt;Tipagem nominal exige mais cerimônia no código - você precisa declarar explicitamente as relações entre tipos - mas em troca oferece contratos mais claros e verificáveis. É mais fácil saber exatamente o que uma função aceita e o que ela rejeita. Tipagem estrutural é mais flexível e menos verbosa, mas exige mais atenção do desenvolvedor: dois tipos podem ser compatíveis por acidente, simplesmente por terem os mesmos métodos, mesmo que representem conceitos completamente diferentes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Onde cada linguagem se encaixa
&lt;/h2&gt;

&lt;p&gt;Com os três eixos em mente, fica mais fácil comparar as linguagens de forma objetiva. A tabela abaixo mostra como cada uma se posiciona nesses eixos de tipagem:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Linguagem&lt;/th&gt;
&lt;th&gt;Forte / Fraca&lt;/th&gt;
&lt;th&gt;Estática / Dinâmica&lt;/th&gt;
&lt;th&gt;Nominal / Estrutural&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;Forte&lt;/td&gt;
&lt;td&gt;Estática&lt;/td&gt;
&lt;td&gt;Nominal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C#&lt;/td&gt;
&lt;td&gt;Forte&lt;/td&gt;
&lt;td&gt;Estática&lt;/td&gt;
&lt;td&gt;Nominal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;Forte&lt;/td&gt;
&lt;td&gt;Estática&lt;/td&gt;
&lt;td&gt;Misto (nominal para tipos concretos, estrutural para interfaces)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td&gt;Forte&lt;/td&gt;
&lt;td&gt;Estática&lt;/td&gt;
&lt;td&gt;Estrutural&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Forte&lt;/td&gt;
&lt;td&gt;Dinâmica&lt;/td&gt;
&lt;td&gt;Estrutural&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;td&gt;Forte&lt;/td&gt;
&lt;td&gt;Dinâmica&lt;/td&gt;
&lt;td&gt;Estrutural&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP&lt;/td&gt;
&lt;td&gt;Fraca&lt;/td&gt;
&lt;td&gt;Dinâmica&lt;/td&gt;
&lt;td&gt;Ambíguo (nominal com classes e interfaces, mas historicamente permissivo)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;Fraca&lt;/td&gt;
&lt;td&gt;Dinâmica&lt;/td&gt;
&lt;td&gt;Estrutural&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Nenhuma combinação é universalmente melhor. Cada uma reflete escolhas de design que priorizam coisas diferentes: segurança, flexibilidade, produtividade ou clareza de contrato.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do sistema de tipos mais rígido para o mais permissivo
&lt;/h3&gt;

&lt;p&gt;Considerando os três eixos juntos - onde forte é mais rígido que fraco, estática mais rígida que dinâmica, e nominal mais rígida que estrutural - é possível ordenar as linguagens do sistema de tipos mais restritivo para o mais permissivo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Java, C#&lt;/strong&gt; - forte + estática + nominal: o nível mais alto de restrição, com verificação antecipada e contratos explícitos obrigatórios&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go&lt;/strong&gt; - forte + estática + nominal/estrutural: tão rígido quanto Java e C# na verificação antecipada, mas um pouco mais flexível nas interfaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; - forte + estática + estrutural: verificação antecipada sem exigir declarações explícitas de conformidade&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python, Ruby&lt;/strong&gt; - forte + dinâmica + estrutural: sem coerções, mas erros só aparecem em execução&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP&lt;/strong&gt; - fraca + dinâmica + ambíguo: permissivo por padrão, com rigor opcional via &lt;code&gt;strict_types&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript&lt;/strong&gt; - fraca + dinâmica + estrutural: o sistema de tipos mais permissivo da lista&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Vale lembrar que essa ordenação é uma simplificação. Na prática, a rigidez de um sistema de tipos depende também de como o desenvolvedor usa a linguagem - PHP com &lt;code&gt;strict_types&lt;/code&gt; e mypy no Python, por exemplo, podem se comportar de forma bem mais rígida do que a posição deles na lista sugere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Tipos são um daqueles assuntos que parecem simples até você começar a comparar como linguagens diferentes os tratam. Um mesmo erro pode travar o programa antes de rodar, explodir em produção, ou passar completamente despercebido, dependendo das escolhas que a linguagem faz. Conhecer essas diferenças muda a forma como você lê erros, escolhe ferramentas e escreve código.&lt;/p&gt;

</description>
      <category>tipagem</category>
      <category>typescript</category>
      <category>go</category>
      <category>python</category>
    </item>
  </channel>
</rss>
