### Discriminated Unions Example in TypeScript Source: https://github.com/voxpelli/type-helpers/blob/main/README.md Illustrates the implementation of discriminated unions using @voxpelli/type-helpers. It defines base interfaces, a union type for all declarations, and an example function demonstrating type-safe handling of different declaration types. ```typescript import type { AnyDeclaration, AnyDeclarationType, ValidDeclaration } from '@voxpelli/type-helpers'; interface FooDeclarationExtras { value: unknown } export interface FooDeclarations { bar: FooDeclaration<'bar', { abc: 123 }>, unknown: FooDeclaration<'unknown', unknown>, } export type AnyFooDeclaration = AnyDeclaration; export type AnyFooDeclarationType = AnyDeclarationType; export interface FooDeclaration extends ValidDeclaration { value: Value } ``` ```typescript import type { FooDeclaration } from '@voxpelli/foo'; declare module '@voxpelli/foo' { interface FooDeclarations { xyz: FooDeclaration<'xyz', { xyz: true }> } } ``` ```javascript /** * @param {AnyFooDeclaration} foo */ function timeToFoo (foo) { switch (foo.type) { case 'bar': // foo.value.abc will be know to exist and be a number break; case 'xyz': // If the third party extension has been included, then foo.value.xyz will be know to exist here and be a boolean break; default: // foo.value is eg. unknown here } } ``` -------------------------------- ### TypeScript - MaybePromised Union with Promise Source: https://context7.com/voxpelli/type-helpers/llms.txt Defines the 'MaybePromised' type, which is a union of T and Promise. This is useful for functions that can return values synchronously (T) or asynchronously (Promise), such as those involving caching or I/O operations. The provided examples demonstrate its usage in class methods, validation, and data source implementations, showing how to uniformly handle both synchronous and asynchronous results. ```typescript import type { MaybePromised } from '@voxpelli/type-helpers'; // Flexible async/sync functions interface User { id: number; name: string; email: string; } class UserRepository { private cache = new Map(); // Can return synchronously from cache or async from database getUser(id: number): MaybePromised { const cached = this.cache.get(id); if (cached) { return cached; // Synchronous return } // Asynchronous database fetch return fetch(`/api/users/${id}`) .then(res => res.json()) .then(user => { this.cache.set(id, user); return user; }); } // Handle both sync and async results uniformly async processUser(id: number): Promise { const user = await this.getUser(id); // Works for both sync and async console.log(`Processing user: ${user.name}`); } } const repo = new UserRepository(); repo.processUser(123); // Flexible validation system type ValidationResult = { valid: boolean; errors: string[] }; interface Validator { validate(value: T): MaybePromised; } class SyncValidator implements Validator { validate(value: string): ValidationResult { return { valid: value.length > 0, errors: value.length === 0 ? ['Value cannot be empty'] : [] }; } } class AsyncValidator implements Validator { async validate(value: string): Promise { // Simulate async validation (e.g., checking uniqueness in database) await new Promise(resolve => setTimeout(resolve, 100)); return { valid: value !== 'taken', errors: value === 'taken' ? ['Value already exists'] : [] }; } } async function runValidation(validator: Validator, value: T): Promise { const result: MaybePromised = validator.validate(value); return await result; // Handles both sync and async results } // Data fetching with optional caching interface DataSource { fetch(): MaybePromised; } class CachedDataSource implements DataSource { private cachedData?: T; constructor(private fetchFn: () => Promise) {} fetch(): MaybePromised { if (this.cachedData) { return this.cachedData; // Sync return from cache } return this.fetchFn().then(data => { this.cachedData = data; return data; }); } } async function getData(source: DataSource): Promise { return await source.fetch(); } const dataSource = new CachedDataSource(() => fetch('/api/data').then(r => r.json())); getData(dataSource).then(data => console.log(data)); ``` -------------------------------- ### Importing PartialKeys in JSDoc Source: https://github.com/voxpelli/type-helpers/blob/main/README.md Demonstrates how to import and use the PartialKeys type helper within JSDoc comments for JavaScript projects. This allows for type-safe manipulation of object properties. ```typescript /** @typedef {import('@voxpelli/type-helpers').PartialKeys} PartialKeys */ ``` -------------------------------- ### Importing PartialKeys in TypeScript Source: https://github.com/voxpelli/type-helpers/blob/main/README.md Shows the standard TypeScript import syntax for utilizing the PartialKeys type helper. This enables developers to make specific keys of an interface optional. ```typescript import type { PartialKeys } from '@voxpelli/type-helpers'; ``` -------------------------------- ### Create Extendible Discriminated Unions with AnyDeclaration Source: https://context7.com/voxpelli/type-helpers/llms.txt Demonstrates how to define and use `AnyDeclaration` to create third-party extendible discriminated unions. This pattern allows for module augmentation, enabling external packages to safely add new declaration types to a system. It showcases type safety for configuration and execution of different plugin types. ```typescript import type { AnyDeclaration, AnyDeclarationType, ValidDeclaration } from '@voxpelli/type-helpers'; // Define a plugin system with extendible declarations interface PluginDeclarationExtras { execute: (context: unknown) => void; } export interface PluginDeclarations { logger: PluginDeclaration<'logger', { level: 'info' | 'error' }>; cache: PluginDeclaration<'cache', { ttl: number }>; unknown: PluginDeclaration<'unknown', unknown>; } export type AnyPluginDeclaration = AnyDeclaration; export type AnyPluginDeclarationType = AnyDeclarationType; export interface PluginDeclaration extends ValidDeclaration { config: Config; execute: (context: unknown) => void; } // Usage in application code function runPlugin(plugin: AnyPluginDeclaration) { switch (plugin.type) { case 'logger': // plugin.config.level is typed as 'info' | 'error' console.log(`Logging at level: ${plugin.config.level}`); plugin.execute({}); break; case 'cache': // plugin.config.ttl is typed as number console.log(`Cache TTL: ${plugin.config.ttl}`); plugin.execute({}); break; default: // plugin.config is unknown here plugin.execute({}); } } // Third-party extension in separate package declare module '@voxpelli/type-helpers' { interface PluginDeclarations { metrics: PluginDeclaration<'metrics', { interval: number; endpoint: string }>; } } // Now 'metrics' is available in the discriminated union const metricsPlugin: AnyPluginDeclaration = { type: 'metrics', config: { interval: 5000, endpoint: '/api/metrics' }, execute: () => console.log('Sending metrics') }; ``` -------------------------------- ### Type-Safe Object Creation with ObjectFromEntries (TypeScript) Source: https://context7.com/voxpelli/type-helpers/llms.txt Creates properly typed objects from entry arrays, providing type safety for Object.fromEntries() operations. It requires the '@voxpelli/type-helpers' package and supports dynamic entry construction and filtering. ```typescript import type { ObjectFromEntries, UnknownObjectEntry } from '@voxpelli/type-helpers'; // Type-safe object construction from entries const configEntries = [ ['apiUrl', 'https://api.example.com'], ['timeout', 5000], ['retries', 3], ['debug', false] ] as const; type ConfigObject = ObjectFromEntries; const config: ConfigObject = Object.fromEntries(configEntries) as ConfigObject; // Dynamic entry construction with type inference function createConfig(entries: T): ObjectFromEntries { return Object.fromEntries(entries) as ObjectFromEntries; } const dynamicEntries = [ ['host', 'localhost'], ['port', 8080], ['secure', true] ] as const; const dynamicConfig = createConfig(dynamicEntries); // Filtering and reconstructing objects function filterEntries( obj: T, predicate: (key: keyof T, value: T[keyof T]) => boolean ): Partial { const entries = Object.entries(obj) as UnknownObjectEntry[]; const filtered = entries.filter(([key, value]) => predicate(key as keyof T, value as T[keyof T])); return Object.fromEntries(filtered) as Partial; } ``` -------------------------------- ### Typed Object Iteration with ObjectEntry and ObjectEntries (TypeScript) Source: https://context7.com/voxpelli/type-helpers/llms.txt Provides type-safe alternatives to JavaScript's Object.entries() that preserve key-value pair types through transformations. It requires the '@voxpelli/type-helpers' package. ```typescript import type { ObjectEntry, ObjectEntries } from '@voxpelli/type-helpers'; // Type-safe object iteration interface User { id: number; name: string; email: string; active: boolean; } function logObjectEntries(obj: T) { const entries: ObjectEntries = Object.entries(obj) as ObjectEntries; entries.forEach((entry: ObjectEntry) => { const [key, value] = entry; console.log(`${String(key)}: ${value}`); }); } const user: User = { id: 123, name: 'Alice', email: 'alice@example.com', active: true }; logObjectEntries(user); // Transform object entries with type safety function transformEntries(obj: T): ObjectEntries { return Object.entries(obj).map(([key, value]) => { return [key, typeof value === 'string' ? value.toUpperCase() : value] as ObjectEntry; }) as ObjectEntries; } const transformed = transformEntries(user); // Type: ObjectEntries ``` -------------------------------- ### Implement Type-Safe Declarations with ValidDeclaration Source: https://context7.com/voxpelli/type-helpers/llms.txt Illustrates the use of `ValidDeclaration` for creating type-safe validation rules. This type ensures that the declaration's type name matches a predefined registry, providing strong typing for custom implementations. It's useful for building systems where declarations need to adhere to specific structures and validation logic. ```typescript import type { ValidDeclaration, AnyDeclarationType } from '@voxpelli/type-helpers'; // Create a validation system with typed rules interface ValidationDeclarationExtras { validate: (value: unknown) => boolean; errorMessage: string; } export interface ValidationDeclarations { email: ValidationDeclaration<'email', RegExp>; minLength: ValidationDeclaration<'minLength', number>; custom: ValidationDeclaration<'custom', (value: unknown) => boolean>; } export type AnyValidationType = AnyDeclarationType; export interface ValidationDeclaration extends ValidDeclaration { rule: RuleConfig; validate: (value: unknown) => boolean; errorMessage: string; } // Implementation const emailValidator: ValidationDeclaration<'email', RegExp> = { type: 'email', rule: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, validate: (value) => typeof value === 'string' && emailValidator.rule.test(value), errorMessage: 'Invalid email address' }; const minLengthValidator: ValidationDeclaration<'minLength', number> = { type: 'minLength', rule: 5, validate: (value) => typeof value === 'string' && value.length >= minLengthValidator.rule, errorMessage: 'Value too short' }; // Type error would occur if type name doesn't match: // const invalid: ValidationDeclaration<'nonexistent', string> = { ... } // Error! ``` -------------------------------- ### Making Specific Keys Optional with PartialKeys (TypeScript) Source: https://context7.com/voxpelli/type-helpers/llms.txt Makes specified keys of an object type optional while keeping others required, useful for update operations and partial data handling. It requires the '@voxpelli/type-helpers' package and can be applied to various object types. ```typescript import type { PartialKeys } from '@voxpelli/type-helpers'; // Database entity with optional update fields interface User { id: number; email: string; name: string; createdAt: Date; updatedAt: Date; } // Update DTO where only user-modifiable fields are optional type UserUpdate = PartialKeys; function updateUser(userId: number, updates: Omit): User { const existingUser: User = { id: userId, email: 'old@example.com', name: 'Old Name', createdAt: new Date('2020-01-01'), updatedAt: new Date() }; return { ...existingUser, ...updates, updatedAt: new Date() }; } // API response with optional fields interface ApiResponse { status: number; data: unknown; message: string; timestamp: Date; } type PartialResponse = PartialKeys; function createResponse(status: number, data: unknown, optional?: Partial): PartialResponse { return { status, data, ...optional }; } ``` -------------------------------- ### Equal Type Narrowing with TypeScript Source: https://context7.com/voxpelli/type-helpers/llms.txt The `Equal` type helper checks if one type extends another, returning the input type if true, or `never` otherwise. It's useful for type filtering, validation, and safe value narrowing in TypeScript functions. Dependencies include the '@voxpelli/type-helpers' package. ```typescript import type { Equal } from '@voxpelli/type-helpers'; // Filter union types based on constraints type Primitive = string | number | boolean | null | undefined; type StringOrNumber = string | number | object | null; type OnlyPrimitives = Equal; type Test1 = OnlyPrimitives; // string type Test2 = OnlyPrimitives; // never // Type-safe value narrowing function processValue(value: T): Equal { if (typeof value === 'string' || typeof value === 'number') { return value as Equal; } throw new Error('Value must be string or number'); } const result1 = processValue('hello'); // Type: string const result2 = processValue(42); // Type: number // const result3 = processValue(true); // Would throw at runtime // Conditional API response types interface SuccessResponse { status: 'success'; data: unknown; } interface ErrorResponse { status: 'error'; message: string; } type ApiResponse = SuccessResponse | ErrorResponse; function handleSuccess( response: T ): Equal { if (response.status === 'success') { return response as Equal; } throw new Error('Not a success response'); } // Type validation in generic functions type ValidConfig = Equal; function validateConfig(config: T): config is ValidConfig { return ( typeof config === 'object' && config !== null && 'apiKey' in config && 'endpoint' in config ); } ``` -------------------------------- ### LiteralTypeOf Runtime Type Checking with TypeScript Source: https://context7.com/voxpelli/type-helpers/llms.txt The `LiteralTypeOf` utility maps JavaScript's `typeof` operator results to string literal types, enabling type-safe runtime type checking. It supports primitives, null, array, and function types. This is useful for creating serialization systems and type registries. Requires '@voxpelli/type-helpers'. ```typescript import type { LiteralTypeOf, LiteralTypes } from '@voxpelli/type-helpers'; // Type-safe runtime type checking function getTypeOf(value: T): LiteralTypeOf { if (typeof value === 'string') return 'string' as LiteralTypeOf; if (typeof value === 'number') return 'number' as LiteralTypeOf; if (typeof value === 'boolean') return 'boolean' as LiteralTypeOf; if (typeof value === 'symbol') return 'symbol' as LiteralTypeOf; if (typeof value === 'undefined') return 'undefined' as LiteralTypeOf; if (value === null) return 'null' as LiteralTypeOf; if (Array.isArray(value)) return 'array' as LiteralTypeOf; if (typeof value === 'function') return 'function' as LiteralTypeOf; return 'object' as LiteralTypeOf; } const type1: LiteralTypeOf = 'string'; const type2: LiteralTypeOf = 'number'; const type3: LiteralTypeOf = 'boolean'; const type4: LiteralTypeOf = 'array'; const type5: LiteralTypeOf<{}> = 'object'; // Type-safe serialization system interface Serializer { type: LiteralTypeOf; serialize: (value: T) => string; deserialize: (str: string) => T; } const stringSerializer: Serializer = { type: 'string', serialize: (value) => value, deserialize: (str) => str }; const numberSerializer: Serializer = { type: 'number', serialize: (value) => value.toString(), deserialize: (str) => parseFloat(str) }; const arraySerializer: Serializer = { type: 'array', serialize: (value) => JSON.stringify(value), deserialize: (str) => JSON.parse(str) }; function serialize(value: T, serializer: Serializer): string { const runtimeType = getTypeOf(value); if (runtimeType !== serializer.type) { throw new Error(`Type mismatch: expected ${serializer.type}, got ${runtimeType}`); } return serializer.serialize(value); } console.log(serialize('hello', stringSerializer)); // "hello" console.log(serialize(42, numberSerializer)); // "42" console.log(serialize([1, 2, 3], arraySerializer)); // "[1,2,3]" // Type registry for runtime type operations const typeRegistry: { [K in keyof LiteralTypes]: (value: unknown) => value is LiteralTypes[K] } = { string: (value): value is string => typeof value === 'string', number: (value): value is number => typeof value === 'number', bigint: (value): value is bigint => typeof value === 'bigint', boolean: (value): value is boolean => typeof value === 'boolean', symbol: (value): value is symbol => typeof value === 'symbol', undefined: (value): value is undefined => value === undefined, null: (value): value is null => value === null, array: (value): value is unknown[] => Array.isArray(value), object: (value): value is object => typeof value === 'object' && value !== null && !Array.isArray(value), function: (value): value is () => unknown => typeof value === 'function' }; ``` -------------------------------- ### Enforce String Literals with NonGenericString in TypeScript Source: https://context7.com/voxpelli/type-helpers/llms.txt The NonGenericString utility type ensures that a type parameter is a specific string literal rather than the general 'string' type. This is crucial for building type-safe APIs, such as event systems or configuration managers, where exact string values are required. It prevents the use of generic strings by raising a type error if a non-literal string is provided. ```typescript import type { NonGenericString } from '@voxpelli/type-helpers'; // Type-safe event system with literal event names type EventName = 'user:created' | 'user:updated' | 'user:deleted' | 'order:placed'; function createEventEmitter>() { const listeners = new Map void>>(); return { on>( event: E, handler: (data: Events[E]) => void ) { const handlers = listeners.get(event) || []; handlers.push(handler as (data: unknown) => void); listeners.set(event, handlers); }, emit>( event: E, data: Events[E] ) { const handlers = listeners.get(event) || []; handlers.forEach(handler => handler(data)); } }; } interface MyEvents { 'user:created': { id: number; name: string }; 'user:updated': { id: number; changes: Record }; 'order:placed': { orderId: string; amount: number }; } const emitter = createEventEmitter(); // Valid: string literals work emitter.on('user:created', (data) => { console.log(`User created: ${data.name}`); // data is typed correctly }); emitter.emit('order:placed', { orderId: 'ORD-123', amount: 99.99 }); // Invalid: generic string type would cause type error // const dynamicEvent: string = 'user:created'; // emitter.on(dynamicEvent, (data) => {}); // Type error! // Type-safe configuration keys interface AppConfig { 'api.url': string; 'api.timeout': number; 'cache.enabled': boolean; } function getConfig>(key: K): AppConfig[K] { const config: AppConfig = { 'api.url': 'https://api.example.com', 'api.timeout': 5000, 'cache.enabled': true }; return config[key]; } const apiUrl = getConfig('api.url'); // Type: string const timeout = getConfig('api.timeout'); // Type: number ``` -------------------------------- ### Enforce String Literal Arrays with NonGenericStringArray in TypeScript Source: https://context7.com/voxpelli/type-helpers/llms.txt The NonGenericStringArray utility type validates that all elements within an array are string literals, not generic strings. This is particularly useful for defining collections of string literals, such as allowed HTTP methods for a route or a set of permissions for a role. It ensures type safety by preventing the inclusion of non-literal strings in these predefined sets. ```typescript import type { NonGenericStringArray } from '@voxpelli/type-helpers'; // Type-safe route definitions type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; function defineRoute( path: string, methods: NonGenericStringArray ) { return { path, methods: methods as readonly HttpMethod[], handler: (method: Methods[number]) => { console.log(`Handling ${method} ${path}`); } }; } // Valid: array of string literals const userRoute = defineRoute('/users', ['GET', 'POST'] as const); userRoute.handler('GET'); // Type-safe const orderRoute = defineRoute('/orders', ['GET', 'PUT', 'DELETE'] as const); // Invalid: generic string array would cause type error // const methods: string[] = ['GET', 'POST']; // const invalidRoute = defineRoute('/invalid', methods); // Type error! // Type-safe permission system type Permission = 'read' | 'write' | 'delete' | 'admin'; interface Role

{ name: string; permissions: NonGenericStringArray; } function createRole

( name: string, permissions: NonGenericStringArray

): Role

{ return { name, permissions }; } const editorRole = createRole('editor', ['read', 'write'] as const); const adminRole = createRole('admin', ['read', 'write', 'delete', 'admin'] as const); function hasPermission

( role: Role

, permission: Permission ): boolean { return (role.permissions as readonly Permission[]).includes(permission); } console.log(hasPermission(editorRole, 'write')); // true console.log(hasPermission(editorRole, 'delete')); // false ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.