Kotlin/JS é um compilador de Kotlin para JavaScript que permite criar aplicações frontend e interfaces web na linguagem Kotlin. Ao contrário do TypeScript, Kotlin/JS oferece tipagem estática estrita, suporte a corrotinas e integração perfeita com Kotlin Multiplatform. Desde Kotlin 1.8, o compilador usa um backend baseado em IR para gerar código JavaScript otimizado. De acordo com JetBrains, 2025, Kotlin/JS suporta integração com o ecossistema NPM e TypeScript através da geração automática de arquivos .d.ts.
Principais Pontos
Kotlin/JS é um dos três backends do compilador Kotlin (juntamente com JVM e Native), projetado para traduzir código Kotlin para JavaScript. Desenvolvido pela JetBrains, o Kotlin/JS permite escrever aplicações web em uma linguagem com tipagem estática estrita, mantendo o acesso ao vasto ecossistema de bibliotecas JavaScript através de declarações externas. Desde o primeiro lançamento estável no Kotlin 1.3, o compilador evoluiu de um backend experimental para uma ferramenta pronta para produção usada em projetos industriais.
O principal propósito do Kotlin/JS é o desenvolvimento frontend usando Kotlin em vez de JavaScript ou TypeScript. Os desenvolvedores obtêm todos os recursos da linguagem Kotlin: null safety, funções de extensão, classes de dados, corrotinas e classes seladas. O código JavaScript gerado pode ser executado em qualquer navegador moderno ou em um ambiente Node.js. Kotlin/JS é especialmente valioso em projetos Kotlin Multiplatform, onde o módulo compartilhado (commonMain) está disponível tanto para aplicações móveis quanto web.
O ecossistema Kotlin/JS inclui frameworks para construir interfaces de usuário. Compose Multiplatform para web usa Kotlin/JS como backend alvo, permitindo criar componentes de interface declarativos que rodam no navegador. Soluções alternativas incluem wrappers para React — Kotlin Wrappers, que fornecem uma API type-safe para React, React Router e Redux.
A compilação no Kotlin/JS passa por vários estágios de transformação. O código Kotlin fonte é primeiro compilado em uma representação intermediária (IR), depois otimizado e finalmente o código JavaScript é gerado. Desde Kotlin 1.8, o backend antigo (JsBackend baseado em AST) foi completamente substituído pelo backend IR, que oferece melhor otimização, menor tamanho de código de saída e compatibilidade com TypeScript.
Anteriormente, o Kotlin/JS usava o JsBackend, que trabalhava diretamente com a AST (Árvore Sintática Abstrata). Essa abordagem tinha limitações: dificuldade em suportar otimizações de plataforma, falta de um IR unificado para todos os backends e incapacidade de gerar declarações TypeScript. A transição para o backend IR resolveu esses problemas, unificando a compilação em todos os três backends do Kotlin e abrindo caminho para otimizações entre backends.
Kotlin/JS suporta dois modos de compilação que determinam o formato e a otimização do código de saída. O modo produção usa Webpack para empacotamento, minificação e tree-shaking. O modo desenvolvimento suporta Hot Module Replacement para iteração rápida no desenvolvimento. A seleção do modo é configurada no build.gradle.kts através da configuração js.target.
kotlin {
js {
browser {
webpackTask {
outputFileName = "app.js"
}
}
binaries.executable()
}
}
A integração do Kotlin/JS com o ecossistema NPM é implementada através de um DSL especial no build.gradle.kts. O desenvolvedor declara dependências npm na configuração kotlin, especificando o nome do pacote e a versão. Kotlin/JS obtém automaticamente os pacotes através do gerenciador de pacotes npm ou yarn. Para garantir acesso type-safe a bibliotecas JavaScript, são usadas declarações externas que descrevem os tipos e funções da biblioteca para o compilador Kotlin.
Declarações externas são declarações Kotlin marcadas com a palavra-chave external. Elas informam ao compilador que a implementação da função ou classe está no código JavaScript, não no Kotlin. A JetBrains fornece conjuntos de wrappers prontos para bibliotecas populares como parte do Kotlin Wrappers, incluindo React, React Router, Redux, Emotion e MUI. Para bibliotecas sem wrappers prontos, o desenvolvedor pode escrever declarações externas manualmente ou usar o gerador de ligações TypeScript Dukat.
kotlin {
js {
browser { }
npm {
dependency("react", "18.3.1")
dependency("react-dom", "18.3.1")
devDependency("webpack", "5.92.0")
}
}
}
// Declaração externa para biblioteca JavaScript
@JsModule("date-fns")
external fun formatDistance(
date: Date, baseDate: Date
): String
TypeScript é uma parte integrante da web moderna, e o Kotlin/JS garante compatibilidade com ele através da geração de arquivos .d.ts. Ao configurar js.generateTsDeclarations = true, o compilador cria declarações TypeScript para todas as funções e classes públicas do Kotlin. Isso permite que projetos TypeScript importem módulos Kotlin com suporte completo de tipos. A geração de declarações TypeScript funciona apenas com o backend IR e é uma das principais razões para migrar do backend antigo.
O backend IR (Intermediate Representation) é um backend unificado para as três plataformas Kotlin: JVM, JS e Native. Ele usa uma representação intermediária comum que passa por vários estágios de otimização antes de gerar o código alvo. Para Kotlin/JS, o backend IR tornou-se obrigatório a partir do Kotlin 1.8.0, substituindo o antigo backend baseado em AST, que foi marcado como obsoleto.
As vantagens do backend IR para Kotlin/JS incluem otimização de código melhorada no nível IR, redução do tamanho do bundle através de eliminação de código morto e otimizações inline, bem como suporte para declarações TypeScript. O backend IR também garante o tratamento correto de funções inline, genéricos reified e funções suspend ao traduzir para JavaScript, o que era problemático no backend antigo.
| Característica | Backend antigo (AST) | Backend IR |
|---|---|---|
| Declarações TypeScript | Não suportadas | Geradas automaticamente |
| Eliminação de código morto | Limitada | Completa, no nível IR |
| Funções inline | Problemas de correção | Tratamento correto |
| Genéricos reified | Não suportados | Suportados |
| Tamanho do bundle | Base | 20–30% menor |
Um projeto completo Kotlin/JS começa com a configuração do build.gradle.kts. O plugin kotlin multiplatform permite configurar Kotlin/JS como uma das plataformas alvo. Vamos ver um exemplo de configuração para uma aplicação web com React.
plugins {
kotlin("multiplatform") version "2.0.21"
id("org.jetbrains.kotlin-wrappers") version "1.0.0-pre.775"
}
kotlin {
js {
browser { }
binaries.executable()
generateTsDeclarations = true
}
}
dependencies {
implementation(enwraps(react, reactDom))
}
Após a configuração, é possível escrever componentes React em Kotlin. Kotlin Wrappers fornece uma API type-safe para React, incluindo componentes funcionais, hooks e sintaxe similar a JSX através de construtores DSL. O exemplo do componente Counter demonstra o trabalho com useState e manipuladores de eventos.
@OptIn(ExperimentalWrapperApi::class)
val Counter = FC<Props> {
var count = useState(0)
div {
+"Counter value: ${count.component1()}"
button {
onClick = { count.component2()(count.component1() + 1) }
+"Increment"
}
}
}
fun main() {
createRoot(document.getElementById("root")!!).render(
createElement(Counter)
)
}
A compilação de um projeto Kotlin/JS é feita através de tarefas Gradle. jsDevelopmentRun inicia o servidor de desenvolvimento Webpack com HMR para desenvolvimento. jsProductionExecutableCompileSync gera um bundle de produção com minificação e tree-shaking. O arquivo HTML final que inclui o JavaScript compilado é gerado pelo plugin webpack e colocado em build/dist.
// Iniciar servidor de desenvolvimento com HMR
./gradlew jsDevelopmentRun
// Compilação de produção com minificação
./gradlew jsProductionExecutableCompileSync
// Saída em build/dist/productionExecutable/
TypeScript é o principal concorrente do Kotlin/JS no espaço de JavaScript tipado. Ambas as linguagens compilam para JavaScript e adicionam tipagem estática sobre o JS dinâmico. No entanto, Kotlin/JS oferece várias vantagens: null safety por padrão, classes seladas, corrotinas e integração perfeita com Kotlin Multiplatform. TypeScript, por sua vez, tem uma comunidade maior, mais bibliotecas prontas com tipos e um ecossistema mais maduro.
A produtividade de desenvolvimento com Kotlin/JS pode ser maior para equipes que já usam Kotlin em outras partes do projeto, pois não requer alternância entre linguagens. TypeScript continua sendo a escolha mais popular para projetos web puros onde Kotlin Multiplatform não é usado. No entanto, com a crescente popularidade do Compose Multiplatform para web, Kotlin/JS está ganhando terreno como alternativa ao React e Angular.
| Característica | Kotlin/JS | TypeScript |
|---|---|---|
| Null safety | Por padrão | strictNullChecks opcional |
| Classes seladas | Suportadas | Via union types |
| Corrotinas | Nativamente | Via async/await |
| Integração KMM | Completa | Nenhuma |
| Tamanho da comunidade | Pequena | Enorme |
| Tipos prontos para bibliotecas | Limitados (DefinitelyTyped via Dukat) | DefinitelyTyped (milhares de bibliotecas) |
A escolha entre Kotlin/JS e TypeScript depende do contexto do projeto. Se a equipe já usa Kotlin Multiplatform ou planeja começar, Kotlin/JS é uma escolha lógica para a parte frontend. Para um projeto web isolado, TypeScript continua sendo uma solução mais pragmática devido à disponibilidade de tipos prontos para bibliotecas JavaScript e a um número maior de desenvolvedores no mercado.
Perguntas Frequentes
Sim, a JetBrains fornece Kotlin Wrappers — wrappers Kotlin type-safe para React, React Router e Redux. Eles permitem escrever componentes React em Kotlin com suporte completo para hooks e DSL semelhante ao JSX.
Ao ativar generateTsDeclarations = true, o Kotlin/JS gera arquivos .d.ts para todas as APIs públicas. Projetos TypeScript podem importar módulos Kotlin com tipagem completa como pacotes npm regulares.
O tamanho do bundle depende das bibliotecas usadas. Uma aplicação mínima Hello World ocupa cerca de 300 KB incluindo a stdlib do Kotlin. Com React e Kotlin Wrappers, o tamanho aumenta para 400–600 KB.
Sim, Kotlin/JS pode ser usado para desenvolver funções serverless e utilitários de console em Node.js. Para isso, especifique js.nodejs em vez de js.browser na configuração.
Kotlin/Wasm é um backend experimental para WebAssembly, enquanto Kotlin/JS gera código JavaScript. Wasm oferece maior desempenho, mas tem acesso limitado ao DOM do navegador.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também