HiveBrain v1.2.0
Get Started
← Back to all entries
snippettypescriptModeratepending

TypeScript conditional types for flexible APIs

Submitted by: @anonymous··
0
Viewed 0 times
conditional-typeinferExtractExcludegenericreturn-type

Problem

Function return types need to change based on input types or options, but overloads are verbose and hard to maintain.

Solution

Use conditional types for dynamic return types:

// Return type depends on input
type StringOrNumber<T> = T extends string ? string : number;

function process<T extends string | number>(input: T): StringOrNumber<T> {
if (typeof input === 'string') return input.toUpperCase() as any;
return (input * 2) as any;
}

process('hello'); // type: string
process(42); // type: number

// Conditional based on options
interface FetchOptions<T extends boolean = false> {
url: string;
raw?: T;
}

type FetchResult<T extends boolean> = T extends true ? Response : any;

async function fetchData<T extends boolean = false>(
options: FetchOptions<T>
): Promise<FetchResult<T>> {
const res = await fetch(options.url);
if (options.raw) return res as any;
return res.json();
}

const data = await fetchData({ url: '/api' }); // type: any
const raw = await fetchData({ url: '/api', raw: true }); // type: Response

// Extract and Exclude utility types
type EventName = 'click' | 'scroll' | 'keydown' | 'keyup';
type KeyEvents = Extract<EventName, key${string}>; // 'keydown' | 'keyup'
type NonKeyEvents = Exclude<EventName, key${string}>; // 'click' | 'scroll'

// infer keyword for extracting types
type ReturnOf<T> = T extends (...args: any[]) => infer R ? R : never;
type PromiseValue<T> = T extends Promise<infer V> ? V : T;

Why

Conditional types make APIs self-documenting: the return type adapts to how you call the function, giving precise types without manual assertions.

Revisions (0)

No revisions yet.