Einleitung: Warum die Frage nach @types/* selbst erfahrene Entwickler quält?
Haben Sie schon einmal eine Stunde mit dem Debuggen eines Fehlers verbracht, der sich letztendlich auf die falsche Platzierung eines @types/*-Pakets in der package.json zurückführen ließ? Wenn ja, sind Sie nicht allein. Die Frage „How do I decide whether @types/* goes into dependencies or devDependencies?" hat tausende Aufrufe auf Stack Overflow gesammelt und ist zu einem echten Kopfschmerz für die TypeScript-Community geworden.
Es scheint doch einfach: Typen in devDependencies packen – und fertig. Aber weit gefehlt. Wenn Ihr Projekt zu wachsen beginnt, Drittanbieter-Bibliotheken, Monorepos und CI/CD-Pipelines ins Spiel kommen, kann eine falsche Platzierung der Typen zu fatalen Build-Fehlern, unerwarteten Abstürzen in der Produktion oder, noch schlimmer, zu einem stillen Verlust der Typisierung führen.
In diesem Artikel analysieren wir die Top-5 der häufigsten Fehler bei der Arbeit mit @types/*, lernen, basierend auf realen Szenarien die richtige Entscheidung zu treffen, und erstellen eine Checkliste, die Sie vor Problemen schützt. Bereit? Los geht's!
Fehler Nr. 1: „Alle @types/* immer in devDependencies" – ein Mythos, der Builds zerstört
Der beliebteste Ratschlag im Internet lautet: „Typen sind kein Runtime-Code, daher sollten sie immer in devDependencies sein." Und das ist in 90 % der Fälle tatsächlich richtig. Es gibt jedoch eine wichtige Ausnahme, die oft vergessen wird.
Wann devDependencies die richtige Wahl sind
Wenn Sie eine Anwendung schreiben (einen Webserver mit Express, ein React-Frontend, ein Kommandozeilen-Tool), dann packen Sie alle @types/* getrost in devDependencies. Ihr Endbenutzer kompiliert TypeScript nicht – er führt bereits kompiliertes JavaScript aus. Die Typen werden nur während der Entwicklung benötigt.
// Beispiel für eine Express-Anwendung{ "devDependencies": { "@types/express": "^4.17.21", "@types/node": "^20.11.0", "typescript": "^5.3.3" }}Wann devDependencies ein fataler Fehler sind
Stellen Sie sich nun vor: Sie entwickeln eine Bibliothek, die TypeScript-Typen für externe Nutzer exportiert. Wenn die Typen Ihrer Bibliothek von @types/express abhängen, Sie diese aber in devDependencies abgelegt haben, dann erhält der Nutzer, der Ihre Bibliothek installiert, diese Typen nicht automatisch. Und seine IDE beginnt, rote Unterstreichungen anzuzeigen.
// ❌ Falsch für eine Bibliothek, die Typen exportiert{ "devDependencies": { "@types/express": "^4.17.21" // Der Nutzer sieht diese Typen nicht! }}
// ✅ Richtig{ "dependencies": { "@types/express": "^4.17.21" // Typen sind für die Nutzer verfügbar }}Goldene Regel: Wenn Ihre Bibliothek Typen aus einem @types/*-Paket reexportiert oder diese in der öffentlichen API verwendet, dann muss dieses Paket in dependencies sein. Werden die Typen nur intern verwendet – dann devDependencies.
Fehler Nr. 2: Ignorieren des Unterschieds zwischen „im Code verwenden" und „in Typen verwenden"
Viele Entwickler verwechseln: „Ich importiere doch Request aus express, also muss express in dependencies sein." Das stimmt für das Paket express selbst, aber nicht für seine Typen.
Lassen Sie uns das an einem konkreten Beispiel durchgehen. Es gibt drei Szenarien für die Verwendung des Pakets @types/lodash:
- Szenario A: Sie schreiben
import _ from 'lodash'und verwenden_.chunk(). Die Typen werden nur für die Kompilierung benötigt –devDependencies. - Szenario B: Sie erstellen eine Funktion
function mySort(arr: T[]): T[]und verwenden darin_.orderBy. Die Typen gelangen nicht nach außen –devDependencies. - Szenario C: Sie schreiben
export function proc