Back

Wie man TypeScript nativ in Node.js ausführt

Wie man TypeScript nativ in Node.js ausführt

Node.js 23.6.0 markiert einen Wendepunkt für TypeScript-Entwickler: Sie können jetzt .ts-Dateien direkt ausführen, ohne Transpilierungs-Tools wie ts-node oder tsc zu verwenden. Diese native TypeScript-Unterstützung optimiert Entwicklungsworkflows, indem Build-Schritte eliminiert werden, während die Typsicherheit über Ihre IDE erhalten bleibt.

Dieser Leitfaden behandelt alles, was Sie benötigen, um TypeScript nativ in Node.js auszuführen – von der grundlegenden Einrichtung bis hin zu produktionsrelevanten Überlegungen. Sie lernen, wie Type Stripping funktioniert, welche TypeScript-Features unterstützt werden und wie Sie Ihre Projekte für optimale Kompatibilität konfigurieren.

Wichtige Erkenntnisse

  • Node.js 23.6.0 führt TypeScript-Dateien direkt ohne Transpilierung aus
  • Type Stripping entfernt Annotationen und bewahrt dabei die Code-Struktur
  • Die meisten gängigen TypeScript-Features funktionieren, aber Enums und Namespaces erfordern Workarounds
  • Import-Anweisungen müssen die .ts-Erweiterung enthalten
  • Native Ausführung bietet 2-3x schnellere Startzeiten im Vergleich zu herkömmlichen Tools

Schnellstart: TypeScript in Node.js 23.6.0 ausführen

Beginnen wir mit einer einfachen TypeScript-Datei, um die native Ausführung zu demonstrieren:

// greeting.ts
function greet(name: string): string {
  return `Hello, ${name}!`
}

console.log(greet("TypeScript"))

Mit Node.js 23.6.0 oder höher können Sie diese direkt ausführen:

node greeting.ts

Das war’s – kein Kompilierungsschritt erforderlich. Node.js entfernt die Typ-Annotationen und führt das verbleibende JavaScript aus.

Um Ihre Node.js-Version zu überprüfen:

node --version  # Sollte v23.6.0 oder höher sein

Beim ersten Ausführen sehen Sie eine experimentelle Warnung:

ExperimentalWarning: Type Stripping is an experimental feature and might change at any time

Um diese Warnung in der Entwicklung zu unterdrücken:

node --disable-warning=ExperimentalWarning greeting.ts

Oder setzen Sie es dauerhaft:

export NODE_OPTIONS="--disable-warning=ExperimentalWarning"

Type Stripping in Node.js verstehen

Type Stripping unterscheidet sich grundlegend von der traditionellen TypeScript-Transpilierung. Anstatt TypeScript in JavaScript zu transformieren, entfernt Node.js einfach die Typ-Annotationen und bewahrt dabei die ursprüngliche Code-Struktur.

Folgendes passiert während des Type Stripping:

// Original TypeScript
function calculate(a: number, b: number): number {
  return a + b
}

// Nach Type Stripping (was Node.js ausführt)
function calculate(a        , b        )         {
  return a + b
}

Beachten Sie die Erhaltung der Leerzeichen – dies gewährleistet genaue Zeilennummern für das Debugging ohne Source Maps zu benötigen.

Performance-Vorteile

Die native TypeScript-Ausführung bietet erhebliche Performance-Verbesserungen:

  • Kein Transpilierungs-Overhead: Direkte Ausführung ohne Zwischenschritte
  • Schnellere Startzeiten: ~45ms vs. 120ms mit ts-node
  • Reduzierter Speicherverbrauch: Kein Transpiler im Speicher geladen
  • Vereinfachtes Debugging: Ursprüngliche Zeilennummern erhalten

Evolution der TypeScript-Unterstützung in Node.js

Das Verständnis der Entwicklung hilft Ihnen, den richtigen Ansatz zu wählen:

v22.6.0: Erstes Type Stripping

node --experimental-strip-types app.ts

Nur grundlegende Typ-Entfernung – keine Unterstützung für TypeScript-spezifische Syntax.

v22.7.0: Type Transformation

node --experimental-transform-types app.ts

Unterstützung für Enums und Namespaces durch Transformation hinzugefügt.

v23.6.0: Standard Type Stripping

node app.ts  # Type Stripping standardmäßig aktiviert

Kein Flag für grundlegende TypeScript-Ausführung erforderlich.

Unterstützte TypeScript-Features und Einschränkungen

Was funktioniert

Native TypeScript in Node.js unterstützt die meisten alltäglichen TypeScript-Features:

// ✅ Typ-Annotationen
let count: number = 0

// ✅ Interfaces
interface User {
  id: number
  name: string
}

// ✅ Typ-Aliase
type Status = 'active' | 'inactive'

// ✅ Generics
function identity<T>(value: T): T {
  return value
}

// ✅ Typ-Imports
import type { Config } from './types.ts'

Was nicht funktioniert

Einige TypeScript-spezifische Features erfordern Workarounds:

FeatureUnterstütztWorkaround
EnumsUnion-Typen oder const-Objekte verwenden
NamespacesES-Module verwenden
Parameter-PropertiesExplizite Property-Deklarationen
JSX/TSXTraditionelle Transpilierung verwenden
DecoratorsAuf V8-Unterstützung warten

Beispiel-Workarounds:

// ❌ Enum (nicht unterstützt)
enum Status {
  Active,
  Inactive
}

// ✅ Union-Typ-Alternative
type Status = 'active' | 'inactive'

// ✅ Const-Objekt-Alternative
const Status = {
  Active: 'active',
  Inactive: 'inactive'
} as const

Dateierweiterungen und Modulsysteme

Node.js verwendet Dateierweiterungen zur Bestimmung der Modul-Behandlung:

  • .ts - Folgt dem "type"-Feld in package.json (ESM oder CommonJS)
  • .mts - Wird immer als ESM behandelt
  • .cts - Wird immer als CommonJS behandelt

Wichtig: Lokale Imports müssen die .ts-Erweiterung enthalten:

// ❌ Traditionelles TypeScript
import { utils } from './utils'

// ✅ Node.js natives TypeScript
import { utils } from './utils.ts'

tsconfig.json für natives TypeScript konfigurieren

Obwohl Node.js die tsconfig.json während der Ausführung nicht liest, gewährleistet eine ordnungsgemäße Konfiguration IDE-Unterstützung und Typprüfung:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "moduleResolution": "nodenext",
    "allowImportingTsExtensions": true,
    "rewriteRelativeImportExtensions": false,
    "verbatimModuleSyntax": true,
    "strict": true,
    "noEmit": true
  }
}

Wichtige Einstellungen erklärt:

  • allowImportingTsExtensions: Erlaubt .ts in Import-Pfaden
  • rewriteRelativeImportExtensions: Auf false setzen, um .ts-Erweiterungen zu erhalten
  • verbatimModuleSyntax: Erzwingt explizite Typ-Imports
  • noEmit: Verhindert versehentliche JavaScript-Generierung

Typprüfung separat ausführen:

tsc --noEmit

Migrationsleitfaden von traditionellen TypeScript-Tools

Migration von ts-node

  1. ts-node-Abhängigkeit entfernen:
npm uninstall ts-node
  1. package.json-Skripte aktualisieren:
// Vorher
"scripts": {
  "dev": "ts-node src/index.ts"
}

// Nachher
"scripts": {
  "dev": "node src/index.ts"
}
  1. Nicht unterstützte Features behandeln (Enums zu Unions konvertieren)

Migration von tsc-Kompilierung

  1. Build-Schritte entfernen:
// Diese Skripte entfernen
"scripts": {
  "build": "tsc",
  "start": "node dist/index.js"
}

// Stattdessen verwenden
"scripts": {
  "start": "node src/index.ts"
}
  1. CI/CD-Pipelines aktualisieren, um Kompilierung zu überspringen

Performance-Vergleich

Native TypeScript-Ausführung zeigt erhebliche Verbesserungen:

MetrikNatives TypeScriptts-nodetsc + node
Startzeit~45ms~120ms~200ms
SpeicherverbrauchBaseline+30MB+10MB
Build-SchrittKeinerKeinerErforderlich

Häufige Fallstricke und Lösungen

Import-Pfad-Fehler

// Fehler: Cannot find module './utils'
import { helper } from './utils'

// Lösung: .ts-Erweiterung einschließen
import { helper } from './utils.ts'

Nicht unterstützte Syntax

// Fehler: Enums are not supported
enum Color { Red, Blue }

// Lösung: Const-Objekt verwenden
const Color = { Red: 0, Blue: 1 } as const

Typprüfungs-Verwirrung

Denken Sie daran: Node.js führt keine Typprüfung durch. Führen Sie immer tsc --noEmit für Typ-Validierung aus.

Produktionsüberlegungen

Wann natives TypeScript verwenden

  • Entwicklungsumgebungen
  • Prototypen und Experimente
  • Kleine Skripte und Utilities
  • Teams, die für experimentelle Features bereit sind

Wann vermeiden

  • Produktionsanwendungen (bis stabil)
  • Projekte, die vollständige TypeScript-Features benötigen
  • Teams, die stabile Tooling benötigen
  • Komplexe Build-Pipelines

Docker-Anpassungen

# Vorher
FROM node:23-alpine
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]

# Nachher
FROM node:23-alpine
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["node", "src/index.ts"]

Fazit

Die native TypeScript-Unterstützung in Node.js 23.6.0 stellt eine erhebliche Vereinfachung für Entwicklungsworkflows dar. Durch die Eliminierung von Transpilierungsschritten können Sie sich auf das Schreiben von Code konzentrieren, anstatt Build-Tools zu konfigurieren. Obwohl Einschränkungen bestehen – insbesondere bei TypeScript-spezifischer Syntax – sind die Vorteile für die meisten Entwicklungsszenarien überzeugend.

Beginnen Sie damit, natives TypeScript in Ihrer Entwicklungsumgebung auszuprobieren, migrieren Sie bestehende Projekte schrittweise und bereiten Sie sich auf eine Zukunft vor, in der TypeScript überall dort läuft, wo JavaScript läuft. Da sich dieses Feature stabilisiert, erwarten Sie breitere Adoption und erweiterte Fähigkeiten in kommenden Node.js-Releases.

FAQs

Obwohl technisch möglich, wird es noch nicht für den Produktionseinsatz empfohlen. Das Feature ist noch experimentell und kann sich ändern. Verwenden Sie es für Entwicklungsumgebungen, Prototypen und nicht-kritische Anwendungen. Für die Produktion verwenden Sie weiterhin traditionelle Transpilierung, bis das Feature stabil wird.

Ja, Sie sollten TypeScript als Entwicklungsabhängigkeit behalten für die Typprüfung. Node.js entfernt nur Typen, ohne sie zu validieren. Führen Sie tsc --noEmit separat aus, um Typfehler während der Entwicklung oder in Ihrer CI-Pipeline zu erfassen.

Natives TypeScript erfordert explizite .ts-Erweiterungen in Import-Pfaden, im Gegensatz zu traditionellem TypeScript-Tooling. Aktualisieren Sie alle lokalen Imports von './module' zu './module.ts'. Externe Package-Imports benötigen keine Erweiterungen.

Ersetzen Sie Enums durch Union-Typen für einfache Fälle oder const-Objekte mit as const-Assertion für numerische Enums. Für String-Enums funktionieren Union-Typen perfekt. Dieser Ansatz ist tatsächlich besser tree-shakeable und entspricht modernen TypeScript-Praktiken.

Das Node.js-Team konzentriert sich auf Type Stripping anstatt vollständige Transpilierung aus Performance-Gründen. Features, die Laufzeit-Transformation erfordern wie Enums und Decorators, könnten Unterstützung erhalten, wenn V8 sie nativ implementiert, aber das Ziel ist schnelle, minimale Verarbeitung anstatt vollständige TypeScript-Kompatibilität.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay