NCA Social Media
Aktualisiert:
Autor:
Roland Golla
Türsteher stoppt Kiste mit Fragezeichen vor gelbem Schild UNKNOWN

Was ist der Unterschied zwischen unknown und any?

unknown und any nehmen beide jeden Wert an. Der Unterschied liegt danach: Mit any darfst du sofort alles tun, mit unknown erst, wenn du geprüft hast, was drinsteckt. any schaltet die Typprüfung an dieser Stelle ab, unknown behält sie und verlangt eine Einordnung.
Praktisch heißt das: any ist ein Loch im Typsystem, unknown ist eine Tür mit Türsteher. Beide lassen alles herein, nur eine der beiden fragt nach.
Code:
          

function mitAny(wert: any) {
  wert.toUpperCase(); // kompiliert, kracht bei einer Zahl
}

function mitUnknown(wert: unknown) {
  wert.toUpperCase();
  // Fehler: 'wert' is of type 'unknown'.

  if (typeof wert === "string") {
    wert.toUpperCase(); // hier ist es sicher
  }
}

Die Faustregel für den Alltag: An jeder Stelle, an der du any schreiben willst, schreibst du unknown und prüfst danach. In den allermeisten Fällen kostet das drei Zeilen und spart einen Fehler in Production.

unknown statt any mit NCA: Schnelle Hilfe vom Experten

Never Code Alone arbeitet seit über 20 Jahren an Softwarequalität. Unser Frontend Stack aus Astro, React und Vue läuft durchgehend typisiert in Production, Type Checking ist Pflichtschritt in jeder Pipeline. Ein any im Code ist bei uns kein Stilthema, sondern ein Review Befund mit Begründungspflicht. Genau dieselbe Haltung fahren wir im Backend mit PHPStan auf Maximallevel und Type Coverage.

In deinem Projekt heißt das konkrete Arbeit. Wir führen den strict Mode in gewachsenen Codebasen ein, ersetzen any Stück für Stück durch geprüfte Typen und machen mit AI Slop Refactoring KI generierten Code produktionsreif. Im Vibe Coding Consulting verankern wir die Regel dort, wo sie wirkt: in den Quality Gates und den Vibe Coding Best Practices.

TypeScript Projekt absichern

Finde das passende Angebot für dein Projekt

Anfrage-Konfiguration

Starten Sie Ihre Anfrage

Projektart
Infos
Nachricht

Eliminierung technischer Schulden mit PHPStan, Rector PHP und PHPUnit. Über 20 Jahre Praxiserfahrung in skalierbaren Backends.

CORE EXPERTISE

Gesetzliche Konformität & Inklusion. Optimierung von Performance und Conversion durch radikal nutzerzentriertes, universelles Design.

BFSG COMPLIANT

Skalierbare KI-Systeme mit echtem Code Ownership. CI/CD, Backup-Strategien und Infrastruktur, die mit deinem Team wächst.

ENTERPRISE READY

Was any wirklich macht: der Compiler schaut weg

any ist keine Typinformation, sondern deren Abwesenheit. Wo any steht, hört TypeScript auf zu arbeiten. Jeder Property Zugriff ist erlaubt, jeder Methodenaufruf, jede Rechnung. Der Editor macht keine Vorschläge mehr, weil er nichts mehr weiß.
Code:
          

const user: any = ladeNutzer();

user.name.toUpperCase();
user.profil.adresse.strasse;
user.istAktiv();
user + 1;

// Alles kompiliert. Keine einzige dieser Zeilen ist geprüft.

Das eigentliche Problem ist die Ausbreitung. Ein any bleibt selten an einer Stelle. Der Rückgabewert einer Funktion mit any Parameter wird oft selbst any, und über Zuweisungen wandert der Typ weiter durch die Codebase. So entsteht aus einer bequemen Zeile ein Bereich ohne Prüfung.
Dazu kommt das implizite any. Wenn ein Parameter keinen Typ hat und TypeScript keinen ableiten kann, ist er stillschweigend any. Ohne noImplicitAny fällt das nirgends auf, weil im Code gar kein any steht.
Code:
          

// Ohne noImplicitAny: kein Fehler, aber kein Schutz
function formatiere(wert) {
  return wert.trim();
}

formatiere(42); // kracht zur Laufzeit

unknown: alles darf rein, aber nichts ohne Prüfung raus

unknown nimmt genauso jeden Wert an wie any. Der Unterschied kommt beim Zugriff. TypeScript erlaubt keine einzige Operation, solange der Typ nicht eingegrenzt ist. Das Eingrenzen heißt Narrowing und funktioniert mit den Mitteln, die JavaScript ohnehin hat.
Code:
          

function verarbeite(wert: unknown) {
  if (typeof wert === "string") {
    return wert.trim();
  }

  if (typeof wert === "number") {
    return wert.toFixed(2);
  }

  if (wert instanceof Date) {
    return wert.toISOString();
  }

  return "Unbekannter Wert";
}

Für Objekte reicht typeof nicht, weil es nur object meldet. Hier hilft der in Operator oder eine eigene Type Guard Funktion. Eine Type Guard ist eine normale Funktion mit einem besonderen Rückgabetyp, der dem Compiler sagt, was er nach dem Check annehmen darf.
Code:
          

type Nutzer = { name: string; email: string };

function istNutzer(wert: unknown): wert is Nutzer {
  return (
    typeof wert === "object" &&
    wert !== null &&
    "name" in wert &&
    "email" in wert
  );
}

function begruesse(wert: unknown) {
  if (istNutzer(wert)) {
    return "Hallo " + wert.name;
  }
  throw new Error("Kein gueltiger Nutzer");
}

Ein Hinweis zum Ehrlichbleiben: Eine Type Guard prüft nur so gründlich, wie du sie schreibst. Wer nur auf das Vorhandensein eines Feldes prüft, weiß noch nichts über dessen Typ. Für Daten aus dem Netz ist deshalb eine richtige Schema Validierung die bessere Wahl.

any, unknown, never und konkrete Typen im Vergleich

Typ Was du zuweisen darfst Was du damit tun darfst
any Jeden Wert Alles, ohne jede Prüfung
unknown Jeden Wert Nichts, bis der Typ eingegrenzt ist
never Nichts Nichts, der Fall darf nicht eintreten
string, Nutzer, Union Nur passende Werte Alles, was der Typ hergibt

Praxis 1: der Fehler im catch Block

In JavaScript kann alles geworfen werden, nicht nur ein Error. Ein String, eine Zahl, ein beliebiges Objekt. Genau deshalb ist die Variable im catch Block der Klassiker für unknown.
Code:
          

try {
  await speichere(daten);
} catch (fehler) {
  // fehler ist unknown
  if (fehler instanceof Error) {
    logge(fehler.message);
  } else {
    logge("Unbekannter Fehler: " + String(fehler));
  }
}

Der Klassiker im Code Review sieht anders aus: fehler.message wird direkt gelesen. Kommt dort einmal kein Error an, wirft der Error Handler selbst einen Fehler. Der ursprüngliche Fehler ist dann verloren, und im Log steht etwas völlig anderes als das, was tatsächlich passiert ist.
Im strict Mode ist die catch Variable seit TypeScript 4.4 standardmäßig unknown. Wer das isoliert steuern will, nutzt useUnknownInCatchVariables in der tsconfig.json.

Praxis 2: Daten aus dem Netz und aus JSON.parse

Die zweite große Quelle für any ist alles, was über die Leitung kommt. JSON.parse liefert any. Ein fetch mit response.json() liefert ein Promise auf any. In beiden Fällen behauptet niemand etwas über die Daten, es fühlt sich nur so an.
Code:
          

const antwort = await fetch("/api/nutzer");
const daten = await antwort.json(); // any

// Sieht sauber aus, ist aber ungeprüft:
zeigeName(daten.name);

Der erste Schritt ist, den Typ ehrlich zu machen. Statt so zu tun, als kenne man die Struktur, wird die Antwort als unknown behandelt und an genau einer Stelle validiert. Danach ist der Typ echt und nicht behauptet.
Code:
          

const daten: unknown = await antwort.json();

if (istNutzer(daten)) {
  zeigeName(daten.name);
} else {
  throw new Error("Unerwartete API Antwort");
}

Für echte Projekte gehört an diese Stelle eine Schema Validierung statt einer handgeschriebenen Prüfung. Ein Schema beschreibt die erwartete Struktur einmal, validiert zur Laufzeit und liefert den passenden TypeScript Typ gleich mit. Wie sich solche prüfbaren Verträge auch mit KI Agenten nutzen lassen, steht in Schema Based AI Coding.
Wichtig ist die Stelle, nicht das Werkzeug. Validiert wird an der Systemgrenze, also dort, wo fremde Daten hereinkommen. Dahinter arbeitet die Anwendung mit echten Typen. Alles, was den Compiler betrifft, hilft dabei nur bis zur Grenze: satisfies sichert deine eigene Konfiguration ab, nicht die Antwort einer fremden API.

Warum any der häufigste Fund in KI generiertem Code ist

KI Agenten wollen, dass der Code kompiliert. Das ist ihr sichtbarer Erfolg. Wenn ein Typ im Weg steht, ist any der kürzeste Weg zum grünen Ergebnis. Der Fehler ist damit nicht gelöst, sondern nur unsichtbar gemacht.
Das zweite Muster ist die Type Assertion. Aus einem sperrigen Typ wird mit as etwas Passendes behauptet. Beides zusammen erzeugt Code, der durch jede Prüfung läuft und trotzdem falsch sein kann. Genau danach suchen wir zuerst, wenn ein Codebase Audit für KI generierten Code ansteht.
Dagegen hilft keine Ermahnung im Prompt, sondern eine Regel, die der Rechner durchsetzt. Drei Zeilen in der AGENTS.md und ein Linter, der sie prüft.
Code:
          

# Ausschnitt aus AGENTS.md

## TypeScript
- Kein `any`. Fremde Daten sind `unknown` und werden geprueft
- `as` nur mit Kommentar und Begruendung
- Fehler im catch Block sind `unknown`
- Vor jedem Commit: npx tsc --noEmit

Technisch braucht es dafür zwei Schalter. noImplicitAny in der tsconfig.json fängt die unbemerkten Fälle ab, in denen gar kein any im Code steht. Eine Linter Regel gegen explizites any fängt die geschriebenen. Beides zusammen macht die Vorgabe überprüfbar statt freiwillig, so wie wir es in den Quality Gates für KI Code beschreiben.
Der Compiler ist im Agentic Coding das ehrlichste Feedback für einen Agenten. Er lässt sich nicht überreden. Wer ihm mit any den Mund verbietet, verliert genau die Instanz, die den KI Code hätte retten können. Mehr dazu in Code Qualität mit KI Agenten.

any aus einer gewachsenen Codebase entfernen

In einem Projekt mit Historie hilft kein Großreinemachen. Wer alle any auf einmal ersetzt, produziert einen Pull Request, den niemand mehr prüfen kann. Der Weg führt in Stufen, und jede Stufe bleibt grün, bevor die nächste beginnt.
Stufe eins ist Sichtbarkeit. noImplicitAny einschalten und zählen, wie viele Stellen aufleuchten. Diese Zahl ist die ehrlichste Beschreibung des Ist Zustands und gleichzeitig deine Messgröße für alles Weitere.
Stufe zwei sind die Ränder. Alles, was fremde Daten hereinlässt, wird zuerst angefasst: API Antworten, Formulare, Konfiguration aus der Umgebung, catch Blöcke. Dort steckt der größte Nutzen pro geänderter Zeile, weil dort die Fehler entstehen, die später in Production auftauchen.
Stufe drei ist der Rest, sortiert nach Nutzen statt nach Alphabet. Dateien, die häufig geändert werden, kommen zuerst. Code, den seit Jahren niemand angefasst hat, wartet, und manchmal fliegt er stattdessen ganz raus. Welche Bereiche das sind, zeigt ein Blick auf den Modulgraph mit Fallow oder das Aufräumen mit Knip.
Code:
          

// tsconfig.json: Stufe fuer Stufe schaerfen
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "useUnknownInCatchVariables": true
  }
}

Damit die Zahl nur in eine Richtung geht, gehört der Type Check als eigener Schritt in die Pipeline. Ein Check, der nur lokal läuft, wird irgendwann übersprungen. Wie die Stufen zusammenspielen, steht in den Vibe Coding CI CD Pipelines.

Wann any trotzdem in Ordnung ist

Eine Regel ohne Ausnahme wird umgangen. Es gibt Stellen, an denen any die ehrlichere Wahl ist. In Tests etwa, wenn ein Mock bewusst kaputte Daten liefern soll. Oder beim Umgang mit einer alten Library ohne Typen, solange der Zugriff auf eine einzige Datei begrenzt bleibt.
Entscheidend ist die Begrenzung. Ein any an einer klar markierten Stelle mit Kommentar ist verkraftbar. Ein any, das durch die halbe Anwendung wandert, ist es nicht. Deshalb steht es bei uns in einer Zeile, mit Begründung, und nie in einer Funktionssignatur, die von vielen Stellen aufgerufen wird.
Für den Ausnahmefall gibt es die Kombination aus Linter Kommentar und Begründung. Das macht die Entscheidung sichtbar und im nächsten Review überprüfbar, statt sie stillschweigend im Code zu vergraben.

A new top type unknown which is the type-safe counterpart of any.

Anders Hejlsberg, Lead Architect TypeScript bei Microsoft – Pull Request New unknown top type auf GitHub

Aus der NCA Praxis: eine Zeile Regel, die viele Fehler erspart

Kein any im Projektcode, fremde Daten sind unknown und werden an der Grenze geprüft. Diese eine Regel entfernt mehr Laufzeitfehler als jede zusätzliche Testsuite, und sie ist in zehn Minuten eingeführt. Die passenden Bausteine dazu stehen im NCA TypeScript Glossar: der never Type für vollständige Fallunterscheidungen und satisfies für geprüfte Konfiguration. Die Einordnung der Sprache insgesamt steht im TypeScript Glossareintrag, der Weg zum strict Mode mit Astro daneben.

Im Backend gilt dasselbe Prinzip mit anderen Werkzeugen. PHPStan, Psalm und Rector halten Symfony Projekte sauber. Wer mit Agenten arbeitet, findet die Auswahl in den Vibe Coding Modellen, etwa OpenCode. Sicherheitsfragen behandeln wir unter Vibe Coding Security, festgefahrene Projekte bringt Vibe Coding Projekt retten wieder in Gang, und Teams schulen wir im KI Training für Entwicklerteams.

CYPRESS.IO Ambassador und IT Consultant für QA Engenieering und Qualität in PHP Projekten.

Frontend 2025: Optimieren Sie Ihre Webseite mit Astro JS und nutzen Sie die Vorteile der Barrierefreiheit

Optimieren Sie Ihre Webseite mit Astro JS und nutzen Sie die Vorteile einer schnellen, sicheren und barrierefreien Webseite. Erfüllen Sie die gesetzlichen Anforderungen und verbessern Sie die Benutzererfahrung Ihrer Webseite. Mit Astro JS können Sie die Ladezeit reduzieren, die Sicherheit maximieren und die SEO-Optimierung verbessern. Kontaktieren Sie uns, um mehr zu erfahren und um Ihre Webseite auf ein neues Level zu heben.

Astro JS Frontend E-Mail Kontakt

Häufige Fragen zu unknown und any

Die Fragen, die in Reviews und Trainings zu diesen beiden Typen immer wieder kommen, kurz beantwortet.

Was ist 2026 der Unterschied zwischen unknown und any?

Beide Typen nehmen jeden Wert an. Der Unterschied liegt beim Zugriff. Mit any darfst du sofort jede Operation ausführen, ohne dass TypeScript prüft. Mit unknown erlaubt der Compiler gar nichts, bis du den Typ eingegrenzt hast. any schaltet die Prüfung ab, unknown verschiebt sie an die Stelle, an der du tatsächlich weißt, was im Wert steckt.

Wann sollte ich 2026 unknown statt any verwenden?

Als Standard immer dann, wenn der Typ zur Schreibzeit unbekannt ist. Das betrifft API Antworten, JSON.parse, Formulardaten, Nachrichten aus Message Queues und Fehler im catch Block. In all diesen Fällen ist unknown die ehrliche Beschreibung der Lage und zwingt dich zu genau einer Prüfung an der richtigen Stelle.

Ist any 2026 grundsätzlich verboten?

Nein, aber begründungspflichtig. Es gibt Ausnahmen: Tests mit absichtlich kaputten Mocks oder der Zugriff auf eine alte Library ohne Typdefinitionen. Entscheidend ist die Begrenzung auf eine klar markierte Stelle mit Kommentar. Problematisch wird any erst, wenn es in Signaturen steht und sich von dort durch die Codebase ausbreitet.

Wie erkenne ich 2026 verstecktes any im Projekt?

Mit noImplicitAny in der tsconfig.json. Ohne diese Option sind Parameter ohne Typannotation stillschweigend any, obwohl im Code nirgends any steht. Nach dem Einschalten zeigt der Compiler alle betroffenen Stellen auf einmal. Diese Zahl ist ein guter Startwert für ein Refactoring, weil sie den Fortschritt messbar macht.

Hilft unknown 2026 gegen Fehler in KI generiertem Code?

Ja, an einer sehr konkreten Stelle. KI Agenten greifen zu any, wenn ein Typfehler den Weg zum kompilierenden Code versperrt. Der Fehler verschwindet damit aus der Anzeige, nicht aus dem Programm. Eine Regel in der AGENTS.md plus noImplicitAny und eine Linter Regel machen aus der Vorgabe eine Prüfung, die der Rechner durchsetzt.

Wie grenze ich einen unknown Wert ein?

Mit den Mitteln, die JavaScript ohnehin hat. typeof für primitive Typen, instanceof für Klassen und Date, der in Operator für Objektfelder. Für komplexere Strukturen schreibst du eine Type Guard Funktion mit dem Rückgabetyp wert is Nutzer. Der Compiler übernimmt danach die Annahme und lässt dich mit dem konkreten Typ weiterarbeiten.

Warum liefert JSON.parse any statt unknown?

Das ist eine historische Entscheidung in den Typdefinitionen der Standardbibliothek. Eine Umstellung auf unknown wäre für unzählige Projekte ein Bruch. Praktisch löst du es selbst, indem du das Ergebnis explizit als unknown deklarierst und anschließend validierst. Eine Zeile, die den Rest der Anwendung vor ungeprüften Daten schützt.

Reicht eine Type Guard für Daten aus einer API?

Für einfache Fälle ja, für echte Schnittstellen selten. Eine handgeschriebene Prüfung testet meist nur, ob Felder vorhanden sind, nicht ob deren Typen stimmen, und sie veraltet mit jeder Änderung am Schema. Für Daten aus dem Netz gehört an die Systemgrenze eine Schema Validierung, die zur Laufzeit prüft und den passenden Typ gleich mitliefert.

Was ist der Unterschied zwischen unknown und never?

unknown ist der Typ, dem alles zugewiesen werden darf und mit dem nichts erlaubt ist, bis geprüft wurde. never ist das Gegenteil: Ihm darf gar nichts zugewiesen werden. never markiert Fälle, die nicht eintreten dürfen, und ist deshalb das Werkzeug für vollständige Fallunterscheidungen bei Union Types.

Kostet unknown zur Laufzeit Performance?

Der Typ selbst nicht, er existiert nur beim Kompilieren. Was Laufzeit kostet, sind die Prüfungen, die du dadurch schreibst, also typeof Abfragen oder eine Schema Validierung. Diese Kosten fallen an genau den Stellen an, an denen sonst ungeprüfte Daten durchlaufen würden, und sind in jedem realistischen Szenario gut investiert.

Wie überzeuge ich mein Team, any zu verbannen?

Nicht mit einer Diskussion, sondern mit Zahlen. Schalte noImplicitAny ein und zeige die Anzahl der Fundstellen. Nimm danach die Ränder zuerst, also API Zugriffe und catch Blöcke, und miss den Fortschritt. Wenn die Zahl sichtbar sinkt und die Pipeline grün bleibt, erledigt sich die Grundsatzdebatte von selbst.

Was ist mit einer Type Assertion auf unknown?

Ein wert as Nutzer hinter einem unknown hebt genau die Sicherheit wieder auf, für die du unknown gewählt hast. Du behauptest dann etwas, statt es zu prüfen. Wo eine Assertion unvermeidbar ist, gehört ein Kommentar mit Begründung daneben, damit im nächsten Review erkennbar bleibt, worauf die Annahme beruht.