Pureline

Pureline TypeScript

Starke Grenzen, inferierte Interna.

Pureline TypeScript erbt alle Regeln von Pureline JavaScript. Dazu kommt ein klares Typ-Modell: explizite Typen an API-Grenzen, Inferenz im Inneren, unknown statt any und Unions statt Zeremonie.

Erbt alle Regeln von Pureline JavaScript.

Strong TypingInferenceunknown > anyUnions & Types
7Profilregeln
21automatisiert
TypeScript-Code prüfen

Profilregeln

PL-TS-001 Checker

any vermeiden

any schaltet das Typsystem ab. Wirklich unbekannte Daten sind unknown und werden an der Grenze validiert.

Avoid
function load(value: any): any {
}
any durch die Hintertür
const config = JSON.parse(raw) as unknown as Config;
Pureline
function load(value: UserId): User {
}
Unbekannte Daten
function parse(input: unknown): Config {
}
PL-TS-002

Typen bewusst einsetzen

Inferierte und explizite lokale Typen sind beide Pureline-konform. Eine Annotation ist nicht redundant, nur weil TypeScript den Typ auch inferieren könnte.

Explizite Typen lohnen sich besonders, wenn sie die Absicht klarer machen, einen erwarteten Vertrag dokumentieren, eine Grenze vor ungewollter Verbreiterung schützen, das Refactoring absichern oder Code verständlich machen, ohne die ganze Aufrufkette zu verfolgen.

Inferenz soll Lärm entfernen. Sie ist nie eine Regel gegen das Typsystem.

Avoid
Ungewollte Verbreiterung
let state = "idle";
// state ist jetzt string, jeder Tippfehler kompiliert
state = "redy";
Pureline
Inferenz, wenn offensichtlich
const user = loadUser();
Explizit, ebenso gültig
const user: User = loadUser();
Explizit schützt den Vertrag
let state: SessionState = "idle";
PL-TS-003 Checker

Kein I-Prefix

Das I-Prefix ist eine reine Java-Konvention von Pureline. TypeScript-Interfaces heißen nach ihrer Rolle. Das Prefix ist profilspezifisch: Java und Emvus verwenden es, TypeScript nicht.

Avoid
interface ISession {
}
Pureline
interface Session {
}
PL-TS-004 Checker

interface vs. type

interface für objektartige Verträge. type für Unions, Aliase und Funktionssignaturen.

Avoid
Objekt-Vertrag als type
type User = {
    id: string;
    name: string;
};
Signatur als interface
interface Handler {
    (packet: Packet): Promise<void>;
}
Pureline
Objekt-Vertrag
interface User {
    id: string;
    name: string;
}
Union
type SessionState = "ready" | "closed" | "failed";
Signatur
type Handler = (packet: Packet) => Promise<void>;
PL-TS-005 Checker

Union Types statt Enums

Ein enum nur dann, wenn das Konstrukt echten Mehrwert liefert. Für einfache Zustände ist ein Union Type klarer.

Avoid
enum State {
    Idle = "idle",
    Ready = "ready",
    Closed = "closed"
}
Pureline
type State = "idle" | "ready" | "closed";
PL-TS-006 Checker

Starke Typen an Grenzen, Freiheit im Inneren

Öffentliche APIs, externe Daten, Persistenzgrenzen und Netzwerk-Payloads zeigen normalerweise klare Typen.

Innerhalb einer Implementierung sind explizite Annotationen und Inferenz gleichermaßen gültig. Gewählt wird die Form, die den Code am leichtesten verständlich macht. Weniger Annotationen gelten nicht automatisch als sauberer.

Avoid
Ungetypte API-Grenze
export async function openSession(request, options) {
    const payload = await fetch(url).then(response => response.json());
    return sessions.create(payload);
}
Pureline
export async function openSession(request: Request): Promise<Session | null> {
    const user = await users.load(request.userId);

    if (!user) {
        return null;
    }

    return sessions.create(user);
}
PL-TS-007

Folder Density

Ein TypeScript-Feature- oder Quellordner enthält standardmäßig höchstens **10 produktive Source-Module**.

Barrel-Dateien wie index.ts, reine Deklarationsdateien, Tests, generierte Dateien und reine Metadaten-Dateien zählen nicht mit.

Eine Aufteilung bildet eine echte Verantwortungsgrenze ab.

Pureline
Echte Verantwortungsgrenzen
session/
session/state/
session/transport/
session/storage/

Core-Regeln im TypeScript-Checker

Zusätzlich zu den Profilregeln prüft der Checker für TypeScript diese Regeln aus dem Pureline Core: