All essential TypeScript types in one place providing 70+ utility types and helper functions.
—
Conditional types for runtime type validation and compile-time type detection. These utilities help you validate and work with type characteristics at both compile time and runtime.
Returns Type when type Type and Shape are identical. Otherwise returns never.
type Exact<Type, Shape> = [Type] extends [Shape]
? [Shape] extends [Type]
? Type
: never
: never;Usage Example:
import type { Exact } from "ts-essentials";
type User = { id: number; name: string; };
type UserShape = { id: number; name: string; };
type ExtendedUser = { id: number; name: string; email: string; };
type ExactUser = Exact<User, UserShape>; // User (exact match)
type NotExactUser = Exact<User, ExtendedUser>; // never (not exact)
// Useful for ensuring exact type matches in generics
function processExactType<T, U>(
value: T,
shape: Exact<T, U>
): T {
return value;
}Returns true when type Type is any. Otherwise returns false.
type IsAny<Type> = 0 extends 1 & Type ? true : false;Usage Example:
import type { IsAny } from "ts-essentials";
type CheckAny1 = IsAny<any>; // true
type CheckAny2 = IsAny<unknown>; // false
type CheckAny3 = IsAny<string>; // false
type CheckAny4 = IsAny<never>; // false
// Useful for conditional type logic
type SafeType<T> = IsAny<T> extends true ? unknown : T;
// Runtime usage in type guards
function isAnyType<T>(value: T): value is IsAny<T> extends true ? any : never {
// Implementation for checking if a value came from an 'any' type
return false; // This is conceptual - 'any' detection is compile-time only
}Returns true when type Type is never. Otherwise returns false.
type IsNever<Type> = [Type] extends [never] ? true : false;Usage Example:
import type { IsNever } from "ts-essentials";
type CheckNever1 = IsNever<never>; // true
type CheckNever2 = IsNever<any>; // false
type CheckNever3 = IsNever<unknown>; // false
type CheckNever4 = IsNever<string>; // false
// Useful for filtering out never types
type FilterNever<T> = IsNever<T> extends true ? never : T;
type Union = string | never | number;
type Filtered = FilterNever<Union>; // string | number
// Conditional logic based on never detection
type ProcessType<T> = IsNever<T> extends true
? "No valid type"
: `Processing: ${T extends string ? T : "unknown"}`;Returns true when type Type is unknown. Otherwise returns false.
type IsUnknown<Type> = [unknown] extends [Type]
? [Type] extends [unknown]
? true
: false
: false;Usage Example:
import type { IsUnknown } from "ts-essentials";
type CheckUnknown1 = IsUnknown<unknown>; // true
type CheckUnknown2 = IsUnknown<any>; // false
type CheckUnknown3 = IsUnknown<string>; // false
type CheckUnknown4 = IsUnknown<never>; // false
// Useful for providing safer defaults
type SafeDefault<T> = IsUnknown<T> extends true ? string : T;
type Example1 = SafeDefault<unknown>; // string
type Example2 = SafeDefault<number>; // number
// Type-safe unknown handling
type HandleUnknown<T> = IsUnknown<T> extends true
? "Please provide a more specific type"
: T;Returns Type when type Type is tuple. Otherwise returns never.
type IsTuple<Type> = Type extends ReadonlyArray<any>
? number extends Type['length']
? never
: Type
: never;Usage Example:
import type { IsTuple } from "ts-essentials";
type CheckTuple1 = IsTuple<[string, number]>; // [string, number]
type CheckTuple2 = IsTuple<readonly [string, number]>; // readonly [string, number]
type CheckTuple3 = IsTuple<string[]>; // never
type CheckTuple4 = IsTuple<Array<string>>; // never
// Process only tuple types
type ProcessTuple<T> = IsTuple<T> extends never
? "Not a tuple"
: T;
type Result1 = ProcessTuple<[1, 2, 3]>; // [1, 2, 3]
type Result2 = ProcessTuple<number[]>; // "Not a tuple"
// Tuple-specific operations
type TupleLength<T> = IsTuple<T> extends never ? never : T['length'];
type Len1 = TupleLength<[1, 2, 3]>; // 3
type Len2 = TupleLength<string[]>; // neverReturns Object when Object has at least one key. Otherwise returns never.
type NonEmptyObject<Object extends AnyRecord> = keyof Object extends never ? never : Object;Usage Example:
import type { NonEmptyObject } from "ts-essentials";
type CheckObject1 = NonEmptyObject<{ id: number; name: string; }>; // { id: number; name: string; }
type CheckObject2 = NonEmptyObject<{}>; // never
type CheckObject3 = NonEmptyObject<Record<string, never>>; // never
// Ensure objects have properties
function processNonEmptyObject<T extends Record<string, any>>(
obj: NonEmptyObject<T>
): NonEmptyObject<T> {
return obj;
}
// This works
processNonEmptyObject({ id: 1, name: "test" });
// This would cause a compile error:
// processNonEmptyObject({}); // Error: Argument of type '{}' is not assignable
// Conditional processing based on object emptiness
type ProcessObject<T> = NonEmptyObject<T> extends never
? "Empty object"
: keyof T;
type Result1 = ProcessObject<{ a: 1; b: 2; }>; // "a" | "b"
type Result2 = ProcessObject<{}>; // "Empty object"Combine type checkers for complex type validation:
import type { IsAny, IsNever, IsUnknown, IsTuple, NonEmptyObject } from "ts-essentials";
// Complex type validation
type ValidateType<T> =
IsAny<T> extends true ? "Invalid: any type"
: IsNever<T> extends true ? "Invalid: never type"
: IsUnknown<T> extends true ? "Invalid: unknown type"
: T extends object
? NonEmptyObject<T> extends never
? "Invalid: empty object"
: "Valid object type"
: T extends ReadonlyArray<any>
? IsTuple<T> extends never
? "Valid array type"
: "Valid tuple type"
: "Valid primitive type";
type Test1 = ValidateType<{ id: number; }>; // "Valid object type"
type Test2 = ValidateType<[]>; // "Valid tuple type"
type Test3 = ValidateType<string[]>; // "Valid array type"
type Test4 = ValidateType<{}>; // "Invalid: empty object"
type Test5 = ValidateType<any>; // "Invalid: any type"type AnyRecord<T = any> = Record<KeyofBase, T>;
type KeyofBase = string | number | symbol;Install with Tessl CLI
npx tessl i tessl/npm-ts-essentials