Skip to content

Instantly share code, notes, and snippets.

View pfftdammitchris's full-sized avatar
💭
Dreaming

Christopher Tran pfftdammitchris

💭
Dreaming
View GitHub Profile
@pfftdammitchris
pfftdammitchris / snippet-1.ts
Created July 19, 2026 06:05
TypeScript Namespace vs Module in 2026: When Declaration Files Still Need Namespaces - snippet-1.ts
// analytics.d.ts - correct approach
declare namespace Analytics {
interface Config {
apiKey: string;
endpoint: string;
}
function track(event: string, properties?: Record<string, unknown>): void;
function identify(userId: string, traits?: Record<string, unknown>): void;
}
@pfftdammitchris
pfftdammitchris / snippet-2.ts
Created July 19, 2026 06:05
TypeScript Namespace vs Module in 2026: When Declaration Files Still Need Namespaces - snippet-2.ts
// enhanced-websocket.d.ts
declare namespace EnhancedWS {
interface ConnectionOptions {
reconnect: boolean;
maxRetries: number;
timeout: number;
}
interface Message<T = unknown> {
type: string;
@pfftdammitchris
pfftdammitchris / snippet-3.ts
Created July 19, 2026 06:05
TypeScript Namespace vs Module in 2026: When Declaration Files Still Need Namespaces - snippet-3.ts
// dom-extensions.d.ts
declare namespace NodeJS {
interface ProcessEnv {
NEXT_PUBLIC_API_URL: string;
NEXT_PUBLIC_FEATURE_FLAG: string;
}
}
declare interface Window {
gtag: (
@pfftdammitchris
pfftdammitchris / snippet-4.ts
Created July 19, 2026 06:05
TypeScript Namespace vs Module in 2026: When Declaration Files Still Need Namespaces - snippet-4.ts
// express-augmentation.d.ts
import "express";
declare module "express" {
namespace Express {
interface Request {
user?: {
id: string;
email: string;
roles: string[];
@pfftdammitchris
pfftdammitchris / snippet-5.ts
Created July 19, 2026 06:05
TypeScript Namespace vs Module in 2026: When Declaration Files Still Need Namespaces - snippet-5.ts
// winston-augmentation.d.ts
import "winston";
declare module "winston" {
namespace winston {
interface LoggerOptions {
datadogApiKey?: string;
datadogService?: string;
enableCloudWatch?: boolean;
cloudWatchGroup?: string;
@pfftdammitchris
pfftdammitchris / snippet-6.ts
Created July 19, 2026 06:05
TypeScript Namespace vs Module in 2026: When Declaration Files Still Need Namespaces - snippet-6.ts
// legacy-validators.ts
namespace DataValidation {
export namespace Email {
export function isValid(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
export function normalize(email: string): string {
return email.toLowerCase().trim();
}
@pfftdammitchris
pfftdammitchris / snippet-7.ts
Created July 19, 2026 06:05
TypeScript Namespace vs Module in 2026: When Declaration Files Still Need Namespaces - snippet-7.ts
// validators/email.ts
export function isValid(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
export function normalize(email: string): string {
return email.toLowerCase().trim();
}
// validators/phone.ts
@pfftdammitchris
pfftdammitchris / snippet-8.ts
Created July 19, 2026 06:05
TypeScript Namespace vs Module in 2026: When Declaration Files Still Need Namespaces - snippet-8.ts
// broken-mixed-pattern.ts - DO NOT DO THIS
import { logger } from "./logger";
namespace Utils {
export function logError(message: string): void {
// logger is undefined here at runtime
logger.error(message);
}
}
@pfftdammitchris
pfftdammitchris / snippet-9.ts
Created July 19, 2026 06:05
TypeScript Namespace vs Module in 2026: When Declaration Files Still Need Namespaces - snippet-9.ts
// fixed-module-pattern.ts
import { logger } from "./logger";
export function logError(message: string): void {
logger.error(message);
}
@pfftdammitchris
pfftdammitchris / snippet-1.ts
Created July 18, 2026 06:06
TypeScript Generic Constraints in Depth: `extends`, `keyof`, and the Patterns That Prevent Runtime Errors - snippet-1.ts
interface Timestamped {
timestamp: number;
}
function logWithTime<T extends Timestamped>(item: T): void {
console.log(`[${new Date(item.timestamp).toISOString()}]`, item);
}
// Valid: object satisfies constraint
logWithTime({ timestamp: Date.now(), message: "Event" });