Map Type Utilities
Map type utilities provide powerful tools for working with TypeScript Map types, extracting keys and values, and converting between Maps and objects.
Key and Value Extraction
MapKeyOf
Extract the key type from a Map type.
type MapKeyOf<T extends Map<unknown, unknown>> = T extends Map<infer K, unknown> ? K : never;
// Examples
type StringNumberMap = Map<string, number>;
type MapKeys = MapKeyOf<StringNumberMap>; // string
type UserIdMap = Map<'user' | 'admin' | 'guest', User>;
type UserKeys = MapKeyOf<UserIdMap>; // 'user' | 'admin' | 'guest'
MapValueOf
Extract the value type from a Map type.
type MapValueOf<T extends Map<unknown, unknown>> = T extends Map<unknown, infer V> ? V : never;
// Examples
type StringNumberMap = Map<string, number>;
type MapValues = MapValueOf<StringNumberMap>; // number
type UserRoleMap = Map<string, 'admin' | 'user' | 'guest'>;
type RoleValues = MapValueOf<UserRoleMap>; // 'admin' | 'user' | 'guest'
Map Manipulation
OmitMapKey
Create a new Map type with specified keys excluded.
type OmitMapKey<T extends Map<unknown, unknown>, K extends MapKeyOf<T>>
= T extends Map<infer Keys, infer V> ? Map<Exclude<Keys, K>, V> : never;
// Example
type FullConfigMap = Map<'host' | 'port' | 'password' | 'ssl', string>;
type PublicConfigMap = OmitMapKey<FullConfigMap, 'password'>;
// Result: Map<'host' | 'port' | 'ssl', string>
PickMapKey
Create a new Map type with only specified keys included.
type PickMapKey<T extends Map<unknown, unknown>, K extends MapKeyOf<T>>
= T extends Map<unknown, infer V> ? Map<K, V> : never;
// Example
type FullConfigMap = Map<'host' | 'port' | 'password' | 'ssl', string>;
type ConnectionConfigMap = PickMapKey<FullConfigMap, 'host' | 'port'>;
// Result: Map<'host' | 'port', string>
Type Conversion
MapToObject
Convert a Map type to an object type.
type MapToObject<T extends Map<PropertyKey, unknown>>
= T extends Map<infer K, infer V> ? Record<K & PropertyKey, V> : never;
// Examples
type ConfigMap = Map<'host' | 'port', string>;
type ConfigObject = MapToObject<ConfigMap>;
// Result: { host: string; port: string; }
type StatusMap = Map<'loading' | 'success' | 'error', boolean>;
type StatusObject = MapToObject<StatusMap>;
// Result: { loading: boolean; success: boolean; error: boolean; }
ObjectToMap
Convert an object type to a Map type.
type ObjectToMap<T extends Record<PropertyKey, unknown>> = Map<keyof T, T[keyof T]>;
// Examples
interface UserConfig {
theme: 'light' | 'dark';
language: string;
notifications: boolean;
}
type UserConfigMap = ObjectToMap<UserConfig>;
// Result: Map<'theme' | 'language' | 'notifications', 'light' | 'dark' | string | boolean>
Real-World Examples
Configuration Management
import type { MapKeyOf, MapToObject, MapValueOf, OmitMapKey } from 'typescript-api-pro';
// Database configuration as Map
type DatabaseConfigMap = Map<
'host' | 'port' | 'database' | 'username' | 'password' | 'ssl',
string | number | boolean
>;
// Extract key and value types
type ConfigKeys = MapKeyOf<DatabaseConfigMap>; // 'host' | 'port' | 'database' | 'username' | 'password' | 'ssl'
type ConfigValues = MapValueOf<DatabaseConfigMap>; // string | number | boolean
// Create public configuration (without sensitive data)
type PublicConfigMap = OmitMapKey<DatabaseConfigMap, 'password' | 'username'>;
// Convert to object for JSON serialization
type PublicConfigObject = MapToObject<PublicConfigMap>;
// Result: { host: string | number | boolean; port: string | number | boolean; database: string | number | boolean; ssl: string | number | boolean; }
// Configuration manager
class ConfigManager {
private config: Map<ConfigKeys, ConfigValues> = new Map();
set<K extends ConfigKeys>(key: K, value: ConfigValues): void {
this.config.set(key, value);
}
get<K extends ConfigKeys>(key: K): ConfigValues | undefined {
return this.config.get(key);
}
getPublicConfig(): PublicConfigObject {
const publicMap = new Map(this.config);
publicMap.delete('password');
publicMap.delete('username');
return Object.fromEntries(publicMap) as PublicConfigObject;
}
}
Cache System
import type { MapKeyOf, MapValueOf, PickMapKey } from 'typescript-api-pro';
// Cache entries with different types
type CacheMap = Map<
'user:123' | 'post:456' | 'settings:global',
User | Post | Settings
>;
type CacheKeys = MapKeyOf<CacheMap>; // 'user:123' | 'post:456' | 'settings:global'
type CacheValues = MapValueOf<CacheMap>; // User | Post | Settings
// User-specific cache
type UserCacheMap = PickMapKey<CacheMap, 'user:123'>;
// Cache manager with type safety
class TypedCache {
private cache: Map<CacheKeys, CacheValues> = new Map();
set<K extends CacheKeys>(
key: K,
value: CacheValues
): void {
this.cache.set(key, value);
}
get<K extends CacheKeys>(key: K): CacheValues | undefined {
return this.cache.get(key);
}
has(key: CacheKeys): boolean {
return this.cache.has(key);
}
delete(key: CacheKeys): boolean {
return this.cache.delete(key);
}
}
State Management
import type { MapToObject, ObjectToMap } from 'typescript-api-pro';
// Application state as object
interface AppState {
user: User | null;
theme: 'light' | 'dark';
language: string;
isLoading: boolean;
}
// Convert to Map for efficient updates
type AppStateMap = ObjectToMap<AppState>;
// State manager
class StateManager {
private state: AppStateMap = new Map();
// Initialize state
constructor(initialState: AppState) {
Object.entries(initialState).forEach(([key, value]) => {
this.state.set(key as keyof AppState, value);
});
}
// Update single state property
setState<K extends keyof AppState>(key: K, value: AppState[K]): void {
this.state.set(key, value);
}
// Get single state property
getState<K extends keyof AppState>(key: K): AppState[K] | undefined {
return this.state.get(key) as AppState[K] | undefined;
}
// Get entire state as object
getAllState(): AppState {
return Object.fromEntries(this.state) as AppState;
}
// Subscribe to state changes
subscribe(callback: (state: AppState) => void): () => void {
// Implementation would include actual subscription logic
return () => {}; // Unsubscribe function
}
}
API Response Mapping
import type { MapKeyOf, MapToObject, MapValueOf } from 'typescript-api-pro';
// API endpoints and their response types
type APIEndpointMap = Map<
'/users' | '/posts' | '/comments',
User[] | Post[] | Comment[]
>;
type Endpoints = MapKeyOf<APIEndpointMap>; // '/users' | '/posts' | '/comments'
type Responses = MapValueOf<APIEndpointMap>; // User[] | Post[] | Comment[]
// Convert to object for easier access
type APIEndpoints = MapToObject<APIEndpointMap>;
// Result: { '/users': User[] | Post[] | Comment[]; '/posts': User[] | Post[] | Comment[]; '/comments': User[] | Post[] | Comment[]; }
// API client with type safety
class APIClient {
private cache: Map<Endpoints, Responses> = new Map();
async fetch<K extends Endpoints>(
endpoint: K
): Promise<Responses> {
// Check cache first
if (this.cache.has(endpoint)) {
return this.cache.get(endpoint)!;
}
// Fetch from API
const response = await fetch(endpoint);
const data = await response.json() as Responses;
// Cache the result
this.cache.set(endpoint, data);
return data;
}
clearCache(): void {
this.cache.clear();
}
getCacheStatus(): Record<Endpoints, boolean> {
const status = {} as Record<Endpoints, boolean>;
const endpoints: Endpoints[] = ['/users', '/posts', '/comments'];
endpoints.forEach((endpoint) => {
status[endpoint] = this.cache.has(endpoint);
});
return status;
}
}
Form Field Mapping
import type { MapKeyOf, MapValueOf, OmitMapKey } from 'typescript-api-pro';
// Form fields with validation rules
type FormFieldMap = Map<
'email' | 'password' | 'confirmPassword' | 'terms',
{
value: string | boolean;
error?: string;
required: boolean;
}
>;
type FieldNames = MapKeyOf<FormFieldMap>; // 'email' | 'password' | 'confirmPassword' | 'terms'
type FieldConfig = MapValueOf<FormFieldMap>; // { value: string | boolean; error?: string; required: boolean; }
// Form without terms (for API submission)
type APIFormMap = OmitMapKey<FormFieldMap, 'terms'>;
// Form validator
class FormValidator {
private fields: FormFieldMap = new Map();
setField(name: FieldNames, config: FieldConfig): void {
this.fields.set(name, config);
}
getField(name: FieldNames): FieldConfig | undefined {
return this.fields.get(name);
}
validate(): boolean {
let isValid = true;
this.fields.forEach((config, name) => {
if (config.required && !config.value) {
this.fields.set(name, {
...config,
error: `${name} is required`
});
isValid = false;
}
});
return isValid;
}
getErrors(): Map<FieldNames, string> {
const errors = new Map<FieldNames, string>();
this.fields.forEach((config, name) => {
if (config.error) {
errors.set(name, config.error);
}
});
return errors;
}
}
Type Safety Benefits
Compile-Time Validation
import type { MapKeyOf, MapValueOf } from 'typescript-api-pro';
// Type-safe Map operations
function processMapEntries<T extends Map<unknown, unknown>>(
map: T,
processor: (key: MapKeyOf<T>, value: MapValueOf<T>) => void
): void {
map.forEach((value, key) => {
processor(key as MapKeyOf<T>, value as MapValueOf<T>);
});
}
// Usage - TypeScript ensures type safety
const userRoles = new Map([
['admin', { permissions: ['read', 'write', 'delete'] }],
['user', { permissions: ['read'] }]
] as const);
processMapEntries(userRoles, (role, config) => {
console.log(`Role ${role} has permissions:`, config.permissions);
// TypeScript knows the exact types of role and config
});