A comprehensive collection of advanced TypeScript utility types for practical development use. This package provides a wide range of type-level utilities to enhance type safety and developer experience in TypeScript projects.
npm install advanced-ts-utility-typesDeepPartial<T>- Makes all properties optional recursivelyDeepRequired<T>- Makes all properties required recursivelyDeepReadonly<T>- Makes all properties readonly recursivelyPickByType<T, U>- Pick properties by their value typeOmitByType<T, U>- Omit properties by their value typeMerge<T, U>- Merge two object typesOptionalKeys<T>- Extract optional property keysRequiredKeys<T>- Extract required property keys
ArrayElement<T>- Extract array element typeNonEmptyArray<T>- Array with at least one elementHead<T>- First element of tupleTail<T>- All elements except firstLast<T>- Last element of tupleReverse<T>- Reverse tuple orderFlattenArray<T>- Flatten nested arraysIncludes<T, U>- Check if array includes type
Parameters<T>- Extract function parametersFirstParameter<T>- Extract first parameterLastParameter<T>- Extract last parameterPromiseReturnType<T>- Extract promise return typeCurry<T>- Curried function typePredicate<T>- Boolean predicate functionTypePredicate<T, U>- Type guard predicate
Capitalize<S>- Capitalize first letterReplace<S, From, To>- Replace string patternReplaceAll<S, From, To>- Replace all occurrencesSplit<S, D>- Split string by delimiterJoin<T, D>- Join string array with delimiterTrim<S>- Remove whitespaceStringLength<S>- Get string lengthStartsWith<S, T>- Check if string starts with patternExtractRouteParams<T>- Extract route parameters
If<C, T, F>- Conditional type selectionIsEqual<T, U>- Check type equalityIsNever<T>- Check if type is neverIsAny<T>- Check if type is anyIsArray<T>- Check if type is arrayIsFunction<T>- Check if type is functionNonNullish<T>- Remove null and undefinedMaybe<T>- Add null and undefined
Brand<T, B>- Create branded typeOpaque<T, B>- Create opaque type- Common branded types:
UserId,Email,URL,UUID,Timestamp - Validation helpers:
createUserId,createEmail,createURL UnBrand<T>- Extract original type from branded type
Runtime type checking functions:
isString,isNumber,isBoolean,isNull,isUndefinedisObject,isArray,isFunctionisNonEmptyString,isNonEmptyArrayhasProperty,hasMethodisInstanceOf,isOneOf
Assertion functions:
assertIsString- Assert value is string (throws if not)assertIsNumber- Assert value is number (throws if not)assertIsNonNull- Assert value is not null or undefined (throws if nullish)
import { DeepPartial, DeepRequired, DeepReadonly, PickByType, OmitByType, Merge, OptionalKeys, RequiredKeys } from 'advanced-ts-utility-types';
interface User {
id?: string;
name: string;
profile: {
email?: string;
age: number;
settings: {
theme: 'light' | 'dark';
notifications?: boolean;
};
};
}
// DeepPartial - Makes all properties optional recursively
type PartialUser = DeepPartial<User>;
// Result: { id?: string; name?: string; profile?: { email?: string; age?: number; settings?: { theme?: 'light' | 'dark'; notifications?: boolean; }; }; }
// DeepRequired - Makes all properties required recursively
type RequiredUser = DeepRequired<User>;
// Result: { id: string; name: string; profile: { email: string; age: number; settings: { theme: 'light' | 'dark'; notifications: boolean; }; }; }
// DeepReadonly - Makes all properties readonly recursively
type ReadonlyUser = DeepReadonly<User>;
// Result: { readonly id?: string; readonly name: string; readonly profile: { readonly email?: string; readonly age: number; readonly settings: { readonly theme: 'light' | 'dark'; readonly notifications?: boolean; }; }; }
// PickByType - Pick properties by their value type
type StringProps = PickByType<User, string>; // { name: string }
type OptionalProps = PickByType<User, string | undefined>; // { id?: string }
// OmitByType - Omit properties by their value type
type NonStringProps = OmitByType<User, string>; // { profile: { ... } }
// Merge - Merge two object types
type UserWithExtra = Merge<User, { createdAt: Date; updatedAt: Date }>;
// Result: { id?: string; name: string; profile: { ... }; createdAt: Date; updatedAt: Date; }
// OptionalKeys - Extract optional property keys
type OptKeys = OptionalKeys<User>; // 'id'
// RequiredKeys - Extract required property keys
type ReqKeys = RequiredKeys<User>; // 'name' | 'profile'import { ArrayElement, NonEmptyArray, Head, Tail, Last, Reverse, FlattenArray, Includes } from 'advanced-ts-utility-types';
type Numbers = [1, 2, 3, 4, 5];
type Colors = ['red', 'green', 'blue'];
type NestedArray = [[1, 2], [3, [4, 5]], 6];
// ArrayElement - Extract array element type
type NumberArrayElement = ArrayElement<number[]>; // number
type ColorElement = ArrayElement<Colors>; // 'red' | 'green' | 'blue'
// NonEmptyArray - Array with at least one element
function processItems<T>(items: NonEmptyArray<T>) {
const first = items[0]; // No undefined check needed
return items.map(item => transform(item));
}
// Head - First element of tuple
type FirstColor = Head<Colors>; // 'red'
type FirstNumber = Head<Numbers>; // 1
// Tail - All elements except first
type RestColors = Tail<Colors>; // ['green', 'blue']
type RestNumbers = Tail<Numbers>; // [2, 3, 4, 5]
// Last - Last element of tuple
type LastColor = Last<Colors>; // 'blue'
type LastNumber = Last<Numbers>; // 5
// Reverse - Reverse tuple order
type ReversedColors = Reverse<Colors>; // ['blue', 'green', 'red']
type ReversedNumbers = Reverse<Numbers>; // [5, 4, 3, 2, 1]
// FlattenArray - Flatten nested arrays
type FlatArray = FlattenArray<NestedArray>; // [1, 2, 3, 4, 5, 6]
// Includes - Check if array includes type
type HasRed = Includes<Colors, 'red'>; // true
type HasYellow = Includes<Colors, 'yellow'>; // falseimport { Parameters, FirstParameter, LastParameter, PromiseReturnType, Curry, Predicate, TypePredicate } from 'advanced-ts-utility-types';
function fetchUser(id: string, options?: { includeProfile: boolean }, metadata?: Record<string, any>): Promise<User> {
// implementation
}
function isString(value: unknown): value is string {
return typeof value === 'string';
}
// Parameters - Extract function parameters (built-in, but included for completeness)
type FetchParams = Parameters<typeof fetchUser>; // [string, { includeProfile: boolean }?, Record<string, any>?]
// FirstParameter - Extract first parameter
type FirstParam = FirstParameter<typeof fetchUser>; // string
// LastParameter - Extract last parameter
type LastParam = LastParameter<typeof fetchUser>; // Record<string, any> | undefined
// PromiseReturnType - Extract promise return type
type UserResult = PromiseReturnType<typeof fetchUser>; // User
// Curry - Curried function type
type CurriedFetch = Curry<typeof fetchUser>;
// Result: (id: string) => (options?: { includeProfile: boolean }) => (metadata?: Record<string, any>) => Promise<User>
// Predicate - Boolean predicate function
type StringPredicate = Predicate<string>; // (value: string) => boolean
// TypePredicate - Type guard predicate
type StringTypePredicate = TypePredicate<unknown, string>; // (value: unknown) => value is stringimport { Capitalize, Replace, ReplaceAll, Split, Join, Trim, StringLength, StartsWith, ExtractRouteParams } from 'advanced-ts-utility-types';
type Message = 'hello world';
type SpacedText = ' hello world ';
type Route = '/api/users/:userId/posts/:postId';
type Words = ['hello', 'world'];
// Capitalize - Capitalize first letter (built-in, but enhanced)
type Capitalized = Capitalize<Message>; // 'Hello world'
// Replace - Replace string pattern
type Replaced = Replace<Message, 'world', 'TypeScript'>; // 'hello TypeScript'
// ReplaceAll - Replace all occurrences
type AllReplaced = ReplaceAll<'hello hello world', 'hello', 'hi'>; // 'hi hi world'
// Split - Split string by delimiter
type SplitWords = Split<Message, ' '>; // ['hello', 'world']
type SplitChars = Split<'abc', ''>; // ['a', 'b', 'c']
// Join - Join string array with delimiter
type Joined = Join<Words, ' '>; // 'hello world'
type JoinedWithDash = Join<Words, '-'>; // 'hello-world'
// Trim - Remove whitespace
type Trimmed = Trim<SpacedText>; // 'hello world'
// StringLength - Get string length
type Length = StringLength<Message>; // 11
// StartsWith - Check if string starts with pattern
type StartsWithHello = StartsWith<Message, 'hello'>; // true
type StartsWithWorld = StartsWith<Message, 'world'>; // false
// ExtractRouteParams - Extract route parameters
type RouteParams = ExtractRouteParams<Route>; // 'userId' | 'postId'import { If, IsEqual, IsNever, IsAny, IsArray, IsFunction, NonNullish, Maybe } from 'advanced-ts-utility-types';
type A = string;
type B = number;
type C = never;
type D = any;
// If - Conditional type selection
type Result1 = If<true, 'yes', 'no'>; // 'yes'
type Result2 = If<false, 'yes', 'no'>; // 'no'
// IsEqual - Check type equality
type Equal1 = IsEqual<string, string>; // true
type Equal2 = IsEqual<string, number>; // false
// IsNever - Check if type is never
type NeverCheck1 = IsNever<never>; // true
type NeverCheck2 = IsNever<string>; // false
// IsAny - Check if type is any
type AnyCheck1 = IsAny<any>; // true
type AnyCheck2 = IsAny<unknown>; // false
// IsArray - Check if type is array
type ArrayCheck1 = IsArray<string[]>; // true
type ArrayCheck2 = IsArray<string>; // false
// IsFunction - Check if type is function
type FunctionCheck1 = IsFunction<() => void>; // true
type FunctionCheck2 = IsFunction<string>; // false
// NonNullish - Remove null and undefined
type NonNull = NonNullish<string | null | undefined>; // string
// Maybe - Add null and undefined
type Nullable = Maybe<string>; // string | null | undefinedimport { Brand, Opaque, UserId, Email, URL, UUID, Timestamp, createUserId, createEmail, createURL, UnBrand } from 'advanced-ts-utility-types';
// Brand - Create branded type
type ProductId = Brand<string, 'ProductId'>;
type Price = Brand<number, 'Price'>;
// Create branded values
const productId = 'prod-123' as ProductId;
const price = 29.99 as Price;
// Opaque - Create opaque type (similar to Brand but more restrictive)
type Token = Opaque<string, 'Token'>;
const token = 'abc123' as Token;
// Pre-defined branded types
const userId: UserId = createUserId('user-123');
const email: Email = createEmail('user@example.com');
const url: URL = createURL('https://example.com');
const uuid: UUID = 'f47ac10b-58cc-4372-a567-0e02b2c3d479' as UUID;
const timestamp: Timestamp = Date.now() as Timestamp;
// UnBrand - Extract original type from branded type
type OriginalUserId = UnBrand<UserId>; // string
type OriginalPrice = UnBrand<Price>; // number
// Usage in functions
function getProduct(id: ProductId): Product {
// id is guaranteed to be a ProductId, not just any string
return database.products.find(p => p.id === id);
}
function calculateTotal(price: Price, quantity: number): Price {
return (price * quantity) as Price;
}import {
isString, isNumber, isBoolean, isNull, isUndefined, isNullish,
isObject, isArray, isFunction, isNonEmptyString, isNonEmptyArray,
hasProperty, hasMethod, isInstanceOf, isOneOf,
assertIsString, assertIsNumber, assertIsNonNull
} from 'advanced-ts-utility-types';
// Basic type guards
function processValue(value: unknown) {
if (isString(value)) {
return value.toUpperCase(); // TypeScript knows value is string
}
if (isNumber(value)) {
return value.toFixed(2); // TypeScript knows value is number
}
if (isArray(value)) {
return value.length; // TypeScript knows value is array
}
}
// Object property checks
function processUser(obj: unknown) {
if (hasProperty(obj, 'name') && isString(obj.name)) {
console.log(`User name: ${obj.name}`);
}
if (hasMethod(obj, 'getName')) {
const name = obj.getName(); // TypeScript knows getName exists
}
}
// Instance and value checks
const isDate = isInstanceOf(Date);
const isValidStatus = isOneOf('active', 'inactive', 'pending');
if (isDate(someValue)) {
console.log(someValue.getFullYear()); // TypeScript knows it's a Date
}
if (isValidStatus(status)) {
// TypeScript knows status is 'active' | 'inactive' | 'pending'
console.log(`Status: ${status}`);
}
// Assertion functions
function validateInput(data: unknown) {
assertIsString(data); // Throws if not string
return data.trim(); // TypeScript knows data is string
}
function processUser(user: User | null) {
assertIsNonNull(user); // Throws if null/undefined
return user.profile.name; // TypeScript knows user is User
}
// Non-empty checks
function processItems(items: unknown[]) {
if (isNonEmptyArray(items)) {
const first = items[0]; // No undefined check needed
return items.map(item => process(item));
}
}
function processText(text: string) {
if (isNonEmptyString(text)) {
return text.charAt(0); // TypeScript knows string is not empty
}
}Contributions are welcome! Please feel free to submit a Pull Request.
MIT
