Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Windows Tipps & SecurityWindows-Update beschädigt wichtige Datenrettungsfunktion(22.09.2026 um 09:04 Uhr)
Sichere ProgrammierungBuilding an Accessible Ecommerce Product Page with WCAG 2.2(22.09.2026 um 03:39 Uhr)
Sichere ProgrammierungGet Your Website Protected in 10 Minutes with SafeLine WAF(22.09.2026 um 08:42 Uhr)
Sichere ProgrammierungIntroduction to SPRINGBOOT(22.09.2026 um 08:42 Uhr)
Windows Tipps & SecurityWindows-Update beschädigt wichtige Datenrettungsfunktion(22.09.2026 um 09:04 Uhr)
Sichere ProgrammierungBuilding an Accessible Ecommerce Product Page with WCAG 2.2(22.09.2026 um 03:39 Uhr)
Sichere ProgrammierungGet Your Website Protected in 10 Minutes with SafeLine WAF(22.09.2026 um 08:42 Uhr)
Sichere ProgrammierungIntroduction to SPRINGBOOT(22.09.2026 um 08:42 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

The Art of the Side Project: How to Ship Fast and Validate Early

7 TypeScript Patterns I Use in Every Project These aren't groundbreaking. They're the boring patterns that prevent bugs and save hours of debugging. 1. The Result Type (No More try/catch Hell) // Instead of throwing…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




7 TypeScript Patterns I Use in Every Project



These aren't groundbreaking. They're the boring patterns that prevent bugs and save hours of debugging.






1. The Result Type (No More try/catch Hell)






// Instead of throwing exceptions everywhere:
function divide(a: number, b: number): number {
if (b === 0) throw new Error("Division by zero");
return a / b;
}

// Use a Result type:
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };

function divide(a: number, b: number): Result<number, string> {
if (b === 0) return { ok: false, error: "Division by zero" };
return { ok: true, value: a / b };
}

// Usage — the compiler FORCES you to handle errors:
const result = divide(10, 0);
if (result.ok) {
console.log(result.value); // TypeScript knows this is number
} else {
console.error(result.error); // TypeScript knows this is string
}






Why this matters: No more "undefined is not a function" because you forgot a try/catch. The type system enforces error handling.






2. Branded Types (Prevent Mixing Up IDs)






// The problem:
function getUser(id: string) { /* ... */ }
function getPost(id: string) { /* ... */ }

// Easy to mix up:
getUser(postId); // TypeScript allows this! But it's wrong!

// The fix — branded types:
type UserId = string & { readonly __brand: 'UserId' };
type PostId = string & { readonly __brand: 'PostId' };

function createUser(id: string): UserId {
return id as UserId;
}

function getUser(id: UserId) { /* ... */ }
function getPost(id: PostId) { /* ... */ }

const userId = createUser('abc');
getUser(userId); // ✅ Works
// getPost(userId); // ❌ TypeScript error! Type 'UserId' is not assignable to 'PostId'






When to use: Anytime you have multiple IDs that look the same (userId, orderId, sessionId) but mean different things.






3. The Builder Pattern for Complex Objects






interface Config {
host: string;
port: number;
database: string;
ssl: boolean;
poolSize: number;
timeout: number;
}

class ConfigBuilder {
private config: Partial<Config> = {};

static create() {
return new ConfigBuilder();
}

withHost(host: string) {
this.config.host = host;
return this; // Chain!
}

withPort(port: number) {
this.config.port = port;
return this;
}

withDatabase(database: string) {
this.config.database = database;
return this;
}

withSSL(ssl = true) {
this.config.ssl = ssl;
return this;
}

withPoolSize(size: number) {
this.config.poolSize = size;
return this;
}

build(): Config {
if (!this.config.host) throw new Error('host is required');
if (!this.config.database) throw new Error('database is required');

return {
host: this.config.host,
port: this.config.port ?? 5432,
database: this.config.database,
ssl: this.config.ssl ?? false,
poolSize: this.config.poolSize ?? 10,
timeout: this.config.timeout ?? 5000,
};
}
}

// Usage — readable, flexible, with defaults:
const config = ConfigBuilder.create()
.withHost('localhost')
.withDatabase('myapp')
.withSSL()
.withPoolSize(20)
.build();









4. Strict Event Emitter Types






// Instead of the loose EventEmitter from Node:
import { EventEmitter } from 'events';

const emitter = new EventEmitter();
emitter.on('data', (payload: unknown) => { /* type safety? nah */ });
emitter.emit('data', 123); // No type check
emitter.emit('typo', 'anything'); // No type check

// Strict typed version:
type EventMap = {
'user:login': { userId: string; timestamp: Date };
'user:logout': { userId: string };
'error': { message: string; code: number };
'data:update': { key: string; value: unknown };
};

class TypedEmitter<Events extends Record<string, unknown>> {
private emitter = new EventEmitter();

on<K extends keyof Events & string>(
event: K,
handler: (payload: Events[K]) => void
) {
this.emitter.on(event, handler as (...args: unknown[]) => void);
return () => this.emitter.off(event, handler as (...args: unknown[]) => void);
}

emit<K extends keyof Events & string>(
event: K,
payload: Events[K]
) {
this.emitter.emit(event, payload);
}
}

// Usage — fully typed:
const bus = new TypedEmitter<EventMap>();

bus.on('user:login', (payload) => {
console.log(payload.userId); // TypeScript knows this is string
console.log(payload.timestamp); // TypeScript knows this is Date
});

bus.on('error', (payload) => {
console.log(payload.code); // TypeScript knows this is number
});

// bus.emit('user:login', { userId: 123 }); // ❌ Error: string expected
// bus.emit('nonexistent', {}); // ❌ Error: not in EventMap









5. The Guard Pattern (Narrow Types in Functions)






interface User {
id: string;
name: string;
role: 'admin' | 'editor' | 'viewer';
email?: string; // Might not be set
}

// Instead of checking everywhere:
function sendEmail(user: User) {
if (!user.email) throw new Error('No email');
// TypeScript still thinks email might be undefined here in some cases
}

// Use type guards:
function hasEmail(user: User): user is User & { email: string } {
return typeof user.email === 'string' && user.email.length > 0;
}

function isAdmin(user: User): user is User & { role: 'admin' } {
return user.role === 'admin';
}

// Now TypeScript knows:
function sendEmail(user: User) {
if (!hasEmail(user)) return; // Guard clause
console.log(user.email.toLowerCase()); // ✅ TypeScript knows email is string
}

function deleteEverything(user: User) {
if (!isAdmin(user)) throw new Error('Unauthorized');
// ✅ TypeScript knows role is 'admin' here
}









6. Zod for Runtime Validation






import { z } from 'zod';

// Define schema once — use for both types AND runtime validation
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1).max(100),
email: z.string().email(),
role: z.enum(['admin', 'editor', 'viewer']),
createdAt: z.string().datetime(),
});

// Infer TypeScript type from schema
type User = z.infer<typeof UserSchema>;

// Validate API responses at runtime:
async function fetchUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
const data = await response.json();

// This throws if data doesn't match schema
return UserSchema.parse(data);
}

// Safe parse (doesn't throw):
const result = UserSchema.safeParse(mysteryData);
if (result.success) {
const user: User = result.data;
} else {
console.error(result.error.flatten());
}






Why Zod over Joi/ Yup? Type inference. Your schema IS your type definition. No duplication.






7. The Async Pool Pattern






// When you need to run many async operations but limit concurrency:
async function asyncPool<T>(
concurrency: number,
items: T[],
fn: (item: T, index: number) => Promise<void>
): Promise<void> {
const executing = new Set<Promise<void>>();

for (const [index, item] of items.entries()) {
const promise = fn(item, index).then(() => {
executing.delete(promise);
});
executing.add(promise);

if (executing.size >= concurrency) {
await Promise.race(executing);
}
}

await Promise.all(executing);
}

// Usage — fetch 100 URLs but only 5 at a time:
const urls = Array.from({ length: 100 }, (_, i) => `https://api.example.com/page/${i}`);

await asyncPool(5, urls, async (url) => {
const response = await fetch(url);
if (!response.ok) console.error(`Failed: ${url}`);
});

// Compare with naive approach (all at once — might crash):
// await Promise.all(urls.map(url => fetch(url))); // 💥 Too many connections









Bonus: The Never-Returning Function






// For functions that always throw (assertions, unreachable code):
function assert(condition: unknown, message: string): asserts condition {
if (!condition) throw new Error(message);
}

function unreachable(x: never): never {
throw new Error(`Unreachable code reached: ${x}`);
}

// Usage:
type Status = 'loading' | 'success' | 'error';

function handleStatus(status: Status): string {
switch (status) {
case 'loading': return 'Loading...';
case 'success': return 'Done!';
case 'error': return 'Failed!';
}
// If you add a new status type, TypeScript will error here
// because the switch is no longer exhaustive
}









Which patterns do you use daily? Drop your favorites in the comments.



Follow @armorbreak for more TypeScript and Node.js content.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten The Art of the Side Project: How to Ship Fast and Validate Early

Thematisch verwandte Begriffe: Side, Project, Ship, Fast · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-55210 | Joplin is an open source note-taking and to-do application that organise…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick