tsx vs tsc vs ts-node
Escolha a ferramenta certa de TypeScript por ambiente - tsx para desenvolvimento e testes rápidos, tsc para dist/ de produção e evite novas adoções de ts-node a menos que restrições de brownfield exijam.
Busque em todas as páginas da documentação
Escolha a ferramenta certa de TypeScript por ambiente - tsx para desenvolvimento e testes rápidos, tsc para dist/ de produção e evite novas adoções de ts-node a menos que restrições de brownfield exijam.
{
"scripts": {
"dev": "node --watch --import tsx src/main.ts",
"build": "tsc -p tsconfig.json",
"start": "node dist/main.js",
"test": "node --import tsx --test src/**/*.test.ts"
},
"devDependencies": {
"typescript": "^5.6.0",
"tsx": "^4.0.0",
"@types/node": "^24.0.0"
}
}Quando usar isso:
ts-node-dev ou nodemon + ts-node// src/main.ts
import { createServer } from 'node:http';
const port = Number(process.env.PORT ?? 3000);
createServer((_req, res) => {
res.end('ok');
}).listen(port, () => console.log(`Ouvindo na porta ${port}`));# Desenvolvimento - sem etapa de compilação separada
npm run dev
# Pipeline de produção
npm run build
npm run start// tsconfig.json - emitir para produção
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"rootDir": "src",
"declaration": true,
"sourceMap": true,
"strict": true
}
}O que isso demonstra:
tsx usa o hook do loader do Node - transforma TS em tempo real via esbuildtsc escreve dist/main.js preservando especificadores de importação ESM com extensões .jsnode puro - sem loader de devDependency no contêiner--watch + tsx substitui nodemon para muitos serviçosimport.meta, ideal para dev/teste.dist/.build.| Ferramenta | Verificação de Tipos | Emissão | Runtime de Produção | Velocidade |
|---|---|---|---|---|
| tsx | Não (apenas transpile) | Não | Apenas Dev/teste | Rápido |
| tsc | Sim | Sim | Sim (dist/) | Moderado |
| ts-node | Parcial | Não | Dev legado | Moderado |
| tsc + tsx | Trabalhos de CI divididos | tsc | node dist | Melhor prática |
{
"scripts": {
"typecheck": "tsc --noEmit",
"dev": "node --watch --import tsx src/main.ts"
}
}Execute typecheck em CI mesmo quando o dev usar tsx - o tsx sozinho ignora erros de tipo.
node dist/main.js no CMD do Docker.tsc --noEmit no gate de CI.tsc não reescreve paths. Correção: importações relativas NodeNext ou etapa pós tsc-alias.tsc emite por module. Correção: alinhar "type" do package.json com a emissão.node --import tsx.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
SWC (@swc-node) | Pipeline SWC do NestJS 11 | Serviço simples que necessita de configuração mínima |
| Bundle esbuild | Artefato Lambda de arquivo único | Servidor Node de vários arquivos com importação dinâmica |
Referências de projeto tsc --build | Monorepos grandes | API de pacote único |
| JS puro (sem TS) | Scripts minúsculos | Equipes padronizadas em TypeScript |
Para executar TS em produção - evite. Para dev/teste - sim. A produção deve executar JS compilado.
Sim - para verificação de tipos e emissão de dist/. tsx não é um verificador de tipos.
node --watch --import tsx src/main.ts no Node 24.
Sim: node --import tsx --test src/**/*.test.ts.
Sim - multi-estágio: npm ci, npm run build, copie dist/ + dependências de produção para a imagem de runtime.
Ambos suportados - SWC compilação mais rápida; tsc padrão mais rigoroso para serviços menores.
node --env-file=.env --import tsx src/main.ts carrega o ambiente antes que o TS seja executado.
node --inspect --import tsx src/main.ts - breakpoints mapeiam via source maps se habilitados.
NodeNext requer especificadores .js na origem para que a emissão corresponda ao runtime.
Não oficialmente, mas novos projetos Node 24 devem padronizar em tsx para ESM em tempo real.
skipLibCheck, referências de projeto e "incremental": true incremental com .tsbuildinfo.
npm run typecheck depois npm run test depois npm run build - falhe rapidamente em tipos.
Versões da Stack: Esta página foi escrita para Node.js 24.18.0 (LTS Ativo), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 e NestJS 11.
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026