CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-utility-types

Utility Types Collection for TypeScript providing comprehensive type-level utilities for static type manipulation.

Pending
Overview
Eval results
Files

flow-utilities.mddocs/

Flow-style Utilities

Flow-style utilities provide TypeScript equivalents of Flow.js utility types, enabling easy migration from Flow to TypeScript and maintaining compatibility with Flow-based codebases.

Import

import { 
  $Keys, $Values, $ReadOnly, $Diff, $PropertyType, $ElementType,
  $Call, $Shape, $NonMaybeType, Class, mixed 
} from 'utility-types';

Key Extraction

$Keys

Get the union type of all keys in an object type.

type $Keys<T extends object> = keyof T;

Usage:

interface User {
  id: number;
  name: string;
  email: string;
}

type UserKeys = $Keys<User>;
// Result: "id" | "name" | "email"

// Use with conditional types
type StringKeys<T> = {
  [K in $Keys<T>]: T[K] extends string ? K : never;
}[keyof T];

type UserStringKeys = StringKeys<User>;
// Result: "name" | "email"

$Values

Get the union type of all values in an object type.

type $Values<T extends object> = T[keyof T];

Usage:

interface StatusCodes {
  OK: 200;
  NOT_FOUND: 404;
  SERVER_ERROR: 500;
}

type StatusCode = $Values<StatusCodes>;
// Result: 200 | 404 | 500

interface User {
  id: number;
  name: string;
  active: boolean;
}

type UserValueTypes = $Values<User>;
// Result: number | string | boolean

Property Access

$PropertyType

Get the type of a specific property in an object.

type $PropertyType<T extends object, K extends keyof T> = T[K];

Usage:

interface User {
  id: number;
  profile: {
    name: string;
    avatar: string;
  };
}

type UserId = $PropertyType<User, 'id'>;
// Result: number

type UserProfile = $PropertyType<User, 'profile'>;
// Result: { name: string; avatar: string; }

// Useful for extracting nested types
type ProfileName = $PropertyType<UserProfile, 'name'>;
// Result: string

$ElementType

Get the type of elements at a given index in an array, tuple, or object.

type $ElementType<T extends { [P in K & any]: any }, K extends keyof T | number> = T[K];

Usage:

// With arrays
type StringArray = string[];
type ArrayElement = $ElementType<StringArray, number>;
// Result: string

// With tuples
type UserTuple = [number, string, boolean];
type FirstElement = $ElementType<UserTuple, 0>;
// Result: number
type SecondElement = $ElementType<UserTuple, 1>;
// Result: string

// With objects (same as $PropertyType)
interface Config {
  timeout: number;
  retries: number;
}
type TimeoutType = $ElementType<Config, 'timeout'>;
// Result: number

Type Transformations

$ReadOnly

Create a deeply readonly version of an object type.

type $ReadOnly<T extends object> = DeepReadonly<T>;

Usage:

interface Settings {
  theme: {
    mode: 'light' | 'dark';
    colors: string[];
  };
  user: {
    name: string;
    preferences: { [key: string]: any };
  };
}

type ReadonlySettings = $ReadOnly<Settings>;
// Result: All properties and nested properties become readonly
// {
//   readonly theme: {
//     readonly mode: 'light' | 'dark';
//     readonly colors: readonly string[];
//   };
//   readonly user: {
//     readonly name: string;
//     readonly preferences: { readonly [key: string]: any };
//   };
// }

// Usage in function parameters
function processSettings(settings: $ReadOnly<Settings>) {
  // settings.theme.mode = 'dark'; // Error: Cannot assign to readonly property
  console.log(settings.theme.mode); // OK: reading is allowed
}

$Diff

Get the set difference of two object types (properties in T but not in U).

type $Diff<T extends U, U extends object> = Pick<T, SetComplement<keyof T, keyof U>>;

Usage:

interface AllProps {
  name: string;
  age: number;
  email: string;
  password: string;
}

interface PublicProps {
  name: string;
  age: number;
  email: string;
}

type PrivateProps = $Diff<AllProps, PublicProps>;
// Result: { password: string; }

// Common pattern: removing default props
interface ComponentProps {
  title: string;
  color: string;
  size: 'small' | 'medium' | 'large';
  onClick: () => void;
}

interface DefaultProps {
  color: string;
  size: 'small' | 'medium' | 'large';
}

type RequiredProps = $Diff<ComponentProps, DefaultProps>;
// Result: { title: string; onClick: () => void; }

$Shape

Make all properties in an object type optional (equivalent to Partial).

type $Shape<T extends object> = Partial<T>;

Usage:

interface User {
  id: number;
  name: string;
  email: string;
}

type PartialUser = $Shape<User>;
// Result: { id?: number; name?: string; email?: string; }

// Useful for update operations
function updateUser(id: number, updates: $Shape<User>) {
  // Can pass any subset of User properties
}

updateUser(1, { name: 'Alice' }); // Valid
updateUser(2, { email: 'bob@example.com', name: 'Bob' }); // Valid
updateUser(3, {}); // Valid

$NonMaybeType

Remove null and undefined from a type.

type $NonMaybeType<T> = NonNullable<T>;

Usage:

type MaybeString = string | null | undefined;
type DefiniteString = $NonMaybeType<MaybeString>;
// Result: string

type MaybeUser = { name: string; age: number } | null | undefined;
type DefiniteUser = $NonMaybeType<MaybeUser>;
// Result: { name: string; age: number }

// Useful in type guards
function assertNonMaybe<T>(value: T): asserts value is $NonMaybeType<T> {
  if (value == null) {
    throw new Error('Value is null or undefined');
  }
}

declare const maybeValue: string | null;
assertNonMaybe(maybeValue);
// maybeValue is now typed as string

Function and Class Types

$Call

Extract the return type from a function type.

type $Call<Fn extends (...args: any[]) => any> = Fn extends (arg: any) => infer RT ? RT : never;

Usage:

function getUserData(id: number): { name: string; email: string } {
  return { name: 'User', email: 'user@example.com' };
}

type UserData = $Call<typeof getUserData>;
// Result: { name: string; email: string }

// With generic functions
function createArray<T>(item: T, count: number): T[] {
  return Array(count).fill(item);
}

type StringArrayCreator = typeof createArray<string>;
type StringArrayResult = $Call<StringArrayCreator>;
// Result: string[]

// Useful for extracting promise types
async function fetchUser(id: number): Promise<User> {
  // ... implementation
}

type FetchUserResult = $Call<typeof fetchUser>;
// Result: Promise<User>

Class

Represent a constructor type for a given instance type.

type Class<T> = new (...args: any[]) => T;

Usage:

class User {
  constructor(public name: string) {}
}

type UserConstructor = Class<User>;
// Result: new (...args: any[]) => User

// Use in factory functions
function createInstance<T>(ctor: Class<T>, ...args: any[]): T {
  return new ctor(...args);
}

const user = createInstance(User, 'Alice');
// user is typed as User

// With generics
class Repository<T> {
  constructor(private items: T[] = []) {}
  
  add(item: T): void {
    this.items.push(item);
  }
}

type StringRepository = Repository<string>;
type StringRepositoryConstructor = Class<StringRepository>;

Flow Compatibility

mixed

Equivalent to TypeScript's unknown type for Flow compatibility.

type mixed = unknown;

Usage:

// When migrating from Flow
function processValue(value: mixed): string {
  // Must use type guards to narrow the type
  if (typeof value === 'string') {
    return value.toUpperCase();
  }
  if (typeof value === 'number') {
    return value.toString();
  }
  return 'unknown';
}

// Prefer unknown in new TypeScript code
function processValueTS(value: unknown): string {
  // Same implementation as above
}

Migration Examples

From Flow to TypeScript

// Flow code:
// type UserKeys = $Keys<User>;
// type UserValues = $Values<User>;
// type ReadonlyUser = $ReadOnly<User>;

// TypeScript with utility-types:
import { $Keys, $Values, $ReadOnly } from 'utility-types';

type UserKeys = $Keys<User>;
type UserValues = $Values<User>;  
type ReadonlyUser = $ReadOnly<User>;

// Gradually migrate to native TypeScript equivalents:
type UserKeysNative = keyof User;
type UserValuesNative = User[keyof User];
type ReadonlyUserNative = DeepReadonly<User>;

Install with Tessl CLI

npx tessl i tessl/npm-utility-types

docs

aliases-guards.md

flow-utilities.md

index.md

mapped-types.md

tile.json