Advanced TypeScript Type Manipulation Techniques and Exercises
This article explores a collection of advanced TypeScript type‑gymnastics techniques—including how to detect never, unknown, and union types, perform type equality checks, map keys, convert tuples to objects, manipulate intersections, use infer with extends, and solve complex recursive challenges such as permutations, combinations, zip, and integer detection—providing detailed code examples and explanations.
Recently I became obsessed with TypeScript type gymnastics, and this article gathers many of my thoughts and solutions.
Determining if a type is never
type IsNever<T> = [T] extends [never] ? true : false;
type IsNever<T> = (() => T) extends () => never ? true : false;The core issue is that never extends never resolves to never because the union‑distribution property treats never as an empty union. Wrapping the type in a tuple or function prevents distribution and yields the correct result.
Determining if a type is unknown
type IsUnknown<T> = T extends unknown ? true : false;
// Incorrect: IsUnknown<2> // trueSince unknown is the top type, the correct check reverses the extends clause:
type IsUnknown<T> = unknown extends T ? true : false;Type Equality
type Equals<A, B> =
(<T>() => T extends A ? 0 : 1) extends
(<T>() => T extends B ? 0 : 1) ? true : false;Most developers use a bidirectional extends check, which works for many cases but fails for any.
Representing Key Types
TypeScript provides the built‑in PropertyKey type:
type PropertyKey = string | number | symbol;Tuple‑to‑Object Mapping
type TupleToObject<T extends [any, any]> = {
[K in T[0]]: T[1];
};
// Example
type X = TupleToObject<['name', 'ly']>; // { name: "ly" }Using Record simplifies this:
type TupleToObject<T extends [any, any]> = Record<T[0], T[1]>;Intersection‑to‑Interface Conversion
type IntersectionToInterface<I> = {
[K in keyof I]: I[K];
};
// Shorter form
type IntersectionToInterface<I> = Omit<I, never>;Using as in Mapped Types for Filtering
type MyOmit<T, L extends keyof T> = {
[K in keyof T as K extends L ? never : K]: T[K];
};
// Example
type X = MyOmit<{ name: 'ly'; age: 27 }, 'name'>; // { age: 27 }Array‑to‑Tuple Mapping
type NumsToStrs<Arr extends readonly number[]> = {
[K in keyof Arr]: `${Arr[K]}`;
};
// Result: type Strs = ["1", "2", "3"]ThisType for Vue‑like APIs
interface ThisType<T> {}
type Computed<C extends Record<string, any>> = {
[K in keyof C]: ReturnType<C[K]>;
};
declare function SimpleVue<D, C extends Record<string, any>, M>(options: {
data: (this: {}) => D;
computed: C & ThisType<Computed<C> & D & M>;
methods: M & ThisType<M & D & Computed<C>>;
}): D & Computed<C> & M;Pattern Matching with infer and extends
Examples include extracting numbers from string literals, counting occurrences in tuples, and inferring the last element of a union.
Recursive Techniques for Loops and Sub‑Problems
Recursion combined with indexed access or pattern matching enables implementations of joins, permutations, combinations, and other combinatorial problems.
Permutation Example
type Permutation<U, E = U> = [U] extends [never]
? []
: E extends U
? [E, ...Permutation<Exclude<U, E>>]
: never;
// Result: type X = ["A", "B", "C"] | ...Zip Utility
type Zip<T extends readonly any[], U extends readonly any[]> =
[T, U] extends [[infer TF, ...infer TR], [infer UF, ...infer UR]]
? [[TF, UF], ...Zip<TR, UR>]
: [];Integer Detection
type Integer<T extends number> = `${T}` extends `${bigint}` ? T : never;The article concludes with reflections on how TypeScript’s type system leverages union distribution, conditional checks, and recursive patterns to create powerful, expressive typings for front‑end development.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
