npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

type-ops

v3.0.3

Published

Type-ops -- type-level operators for TypeScript

Downloads

409

Readme

npm version

type-ops

Type-ops -- a collection of useful operators to make type-level programming in TypeScript easier.

Table of contents

Compatibility

TypeScript ~2.9.0, ^3.0.1.

Install

npm i type-ops

Requirements

For some operators to work properly, strict mode must be enabled.

Dependencies

None.

License

MIT.

TODO

  • [ ] Use dtslint.

Features

Testing & checking utilities

These types can be used to test an arbitrary type for being conformant to a certain constraint.

expect

Induce a compilation error if TActual does not resolve to the type of expected.

Definition
declare const expect: <TActual>() => { toBe(expected: TActual): void; };
Usage
interface I1 {
  p1: string;
}
interface I2 {
  p1: number;
}
// There will be a compilation error if `IsSameT<I1, I2>' does not resolve to `false':
expect<IsSameT<I1, I2>>().toBe(false);

ExpectT

Induce a compilation error if TActual does not resolve to TExpected.

Definition
type ExpectT<TActual extends TExpected, TExpected extends boolean> = never;
Usage
interface I1 { p1: string; }
interface I2 { p1: number; }
// Compilation will fail if `IsSameT<I1, I2>' does not resolve to `false':
type E1 = ExpectT<IsSameT<I1, I2>, false>;

IsFalseT

Check if T is false. Does not distribute over unions.

Definition
type IsFalseT<T extends boolean> = IsSameT<T, false>;

IsNeverT

Check if T is never. Does not distribute over unions.

Definition
type IsNeverT<T> = IsSameT<T, never>;

IsNullableT

Check if T is nullable. Does not distribute over unions.

Definition
type IsNullableT<T> = IsSubtypeOfT<undefined | null, T>;

IsOptionalT

Check if T is optional. Does not distribute over unions.

Definition
type IsOptionalT<T> = IsSubtypeOfT<undefined, T>;

IsSameT

Check if T and U are of the same shape. Does not distribute over unions.

Definition
type IsSameT<T, U> = AndT<IsSubtypeOfT<T, U>, IsSubtypeOfT<U, T>>;

IsSubtypeOfT

Check if T is a subtype of U. Does not distribute over unions.

type IsSubtypeOfT<T, U> = NoDistributeT<T> extends U
  ? true
  : false;

IsTrueT

Check if T is true. Does not distribute over unions.

Definition
type IsTrueT<T extends boolean> = NotT<IsFalseT<T>>;

Property selectors

These types can be thought of as "filters" on property keys of a particular type.

KeyofT

Extract all properties of T. Distributes over unions.

Definition
type KeyofT<T> = T extends any
  ? keyof T
  : never;

NotPropertiesOfSubtypeT

Extract all properties of T which are not a subtype of U.

Definition
type NotPropertiesOfSubtypeT<T, U> = Exclude<keyof T, PropertiesOfSubtypeT<T, U>>;

NotPropertiesOfTypeT

Extract all properties of T which are not of the same shape as U.

Definition
type NotPropertiesOfTypeT<T, U> = Exclude<keyof T, PropertiesOfTypeT<T, U>>;

OptionalPropertiesT

Extract all optional properties of T.

Definition
type OptionalPropertiesT<T> = {
  [K in keyof T]-?: IsOptionalT<T[K]> extends false
    ? never
    : K;
}[keyof T];

PropertiesOfSubtypeT

Extract all properties of T which are a subtype of U.

Definition
type PropertiesOfSubtypeT<T, U> = {
  [K in keyof T]: IsSubtypeOfT<T[K], U> extends false
    ? never
    : K;
}[keyof T];

PropertiesOfTypeT

Extract all properties of T which are of the same shape as U.

Definition
type PropertiesOfTypeT<T, U> = {
  [K in keyof T]: IsSameT<T[K], U> extends false
    ? never
    : K;
}[keyof T];

RequiredPropertiesT

Extract all required properties of T.

Definition
type RequiredPropertiesT<T> = {
  [K in keyof T]-?: IsOptionalT<T[K]> extends false
    ? K
    : never;
}[keyof T];

Type modifiers

These are just mapped conditional types.

JsonT

Represent T after JSON serialization round-trip. Distributes over unions.

Definition
interface _JsonArrayT<T> extends Array<JsonT<T>> { }
type _CleanT<T> = OmitT<T, PropertiesOfTypeT<T, never>>;
type _JsonObjectT<T> = {
  [K in keyof T]: JsonT<T[K]>;
};
type JsonT<T> = T extends string | number | boolean | null
  ? T
  : T extends Function | symbol | undefined
    ? never
    : T extends Array<infer U> | ReadonlyArray<infer U>
      ? _JsonArrayT<U>
      : T extends Map<any, any> | ReadonlyMap<any, any> | WeakMap<any, any> | Set<any> | ReadonlySet<any> | WeakSet<any>
        ? { }
        : T extends { toJSON(key?: any): infer U; }
          ? U
          : _CleanT<_JsonObjectT<T>>;

OmitT

Omit properties K from T.

Definition
type OmitT<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

OverwriteT

Overwrite properties K of T with matching properties of U and add properties which are unique to U.

Definition
type OverwriteT<T, U, K extends keyof T & keyof U = keyof T & keyof U> = OmitT<T, K> & U;
Usage
interface I1 {
  p1: string;
  p2: string;
  p3: string;
}
interface I2 {
  p2: number;
  p3: number;
  p4: number;
}
type I3 = OverrideT<I1, I2>;
const i3: I3 = {
  p1: 'v1',
  p2: 2,
  p3: 3,
  p4: 4,
};

PartialDeepT

Recursively make all properties of T optional.

Definition
interface _PartialDeepArray<T> extends Array<PartialDeepT<T>> { }
interface _PartialDeepReadonlyArray<T> extends ReadonlyArray<PartialDeepT<T>> { }
type _PartialDeepObjectT<T> = {
  [K in keyof T]: PartialDeepT<T[K]>;
};
export type PartialDeepT<T> = T extends Array<infer U>
  ? _PartialDeepArray<U>
  : T extends ReadonlyArray<infer U>
    ? _PartialDeepReadonlyArray<U>
    : T extends Function | PrimitiveT
      ? T
      : Partial<_PartialDeepObjectT<T>>;

ReadonlyDeepT

Recursively make all properties of T readonly.

Definition
interface _ReadonlyDeepArray<T> extends Array<ReadonlyDeepT<T>> { }
interface _ReadonlyDeepReadonlyArray<T> extends ReadonlyArray<ReadonlyDeepT<T>> { }
type _ReadonlyDeepObjectT<T> = {
  [K in keyof T]: ReadonlyDeepT<T[K]>;
};
export type ReadonlyDeepT<T> = T extends Array<infer U>
  ? _ReadonlyDeepArray<U>
  : T extends ReadonlyArray<infer U>
    ? _ReadonlyDeepReadonlyArray<U>
    : T extends Function | PrimitiveT
      ? T
      : Readonly<_ReadonlyDeepObjectT<T>>;

ReplaceT

Replace properties K of T with matching properties of U.

Definition
type ReplaceT<T, U, K extends keyof T & keyof U = keyof T & keyof U> = OmitT<T, K> & Pick<U, K>;
Usage
interface I1 {
  p1: string;
  p2: string;
  p3: string;
  p4: string;
}
interface I2 {
  p2: number;
  p3: number;
  p4: number;
  p5: number;
}
type I3 = ReplaceT<I1, I2, 'p2' | 'p4'>;
const i3: I3 = {
  p1: 'v1',
  p2: 2,
  p3: 'v3',
  p4: 4,
};

RequiredDeepT

Recursively make all properties of T required.

Definition
interface _RequiredDeepArray<T> extends Array<RequiredDeepT<T>> { }
interface _RequiredDeepReadonlyArray<T> extends ReadonlyArray<RequiredDeepT<T>> { }
type _RequiredDeepObjectT<T> = {
  [K in keyof T]: RequiredDeepT<T[K]>;
};
export type RequiredDeepT<T> = T extends Array<infer U>
  ? _RequiredDeepArray<U>
  : T extends ReadonlyArray<infer U>
    ? _RequiredDeepReadonlyArray<U>
    : T extends Function | PrimitiveT
      ? T
      : _RequiredDeepObjectT<Required<T>>;

WithMutableT

Make properties K of T mutable.

Definition
type WithMutableT<T, K extends keyof T> = ReplaceT<T, MutableT<T>, K>;

WithPartialT

Make properties K of T optional.

Definition
type WithPartialT<T, K extends keyof T> = ReplaceT<T, Partial<T>, K>;

WithReadonlyT

Make properties K of T readonly.

Definition
type WithReadonlyT<T, K extends keyof T> = ReplaceT<T, Readonly<T>, K>;

WithRequiredT

Make properties K of T required.

Definition
type WithRequiredT<T, K extends keyof T> = ReplaceT<T, Required<T>, K>;

WritableDeepT

Recursively make all properties of T mutable.

Definition
interface _MutableDeepArray<T> extends Array<MutableDeepT<T>> { }
interface _MutableDeepReadonlyArray<T> extends ReadonlyArray<MutableDeepT<T>> { }
type _MutableDeepObjectT<T> = {
  [K in keyof T]: MutableDeepT<T[K]>;
};
type MutableDeepT<T> = T extends Array<infer U>
  ? _MutableDeepArray<U>
  : T extends ReadonlyArray<infer U>
    ? _MutableDeepReadonlyArray<U>
    : T extends Function | PrimitiveT
      ? T
      : _MutableDeepObjectT<MutableT<T>>;

MutableT

Make all properties of T mutable.

Definition
type MutableT<T> = {
  -readonly [K in keyof T]: T[K];
};

Aliases and interfaces

ConstructorT

A constructor of TInstances from TArguments.

Definition
type ConstructorT<TInstance = object, TArguments extends any[] = any[]> = new(...args: TArguments) => TInstance;

DictT

A dictionary of TValues.

Definition
interface DictT<TValue = any> {
  [propertyKey: string]: TValue;
}

FunctionT

A function mapping TArguments to TResult.

Definition
type FunctionT<TResult = any, TArguments extends any[] = any[]> = (...args: TArguments) => TResult;

NullableT

Make T nullable.

Definition
type NullableT<T> = OptionalT<T> | null;

OptionalT

Make T optional.

Definition
type OptionalT<T> = T | undefined;

PrimitiveT

A primitive.

Definition
type PrimitiveT = string | symbol | number | boolean | undefined | null;

TaggedT

Make tagged type from T using tag TTag. It can be used to create an opaque alias of T.

Definition
declare const _RAW_TYPE: unique symbol;
declare const _TAG_TYPE: unique symbol;
type TaggedT<T, TTag extends PropertyKey> = T & {
  [_RAW_TYPE]: T;
  [_TAG_TYPE]: TTag;
};
Usage
// `I1' is an opaque type alias of `string' tagged w/ `A':
type I1 = UniqueT<string, 'A'>;
// Type assertion must be used to assign raw `string' to its opaque typedef:
let i1: I1 = 'v1' as I1;
i1 = 'v2' as I1;
// i1 = 'v3';  // Compilation will fail.
// Underlying raw type (`string') can be retrieved through lookup type:
const i11: RawT<I1> = i1;

// `I2' has the same shape as `I1':
type I2 = UniqueT<string, 'A'>;
let i2: I2 = 'v4' as I2;
i2 = i1;
i1 = i2;
const i21: RawT<I1> = i1;

// `I3' is an opaque type alias of `string' tagged w/ `B'.
type I3 = UniqueT<string, 'B'>;
let i3: I3 = 'v5' as I3;
// `I1' and `I3' are incompatible:
// i1 = i3;
// i1 = i3 as I1;  // Type assertion will not make any difference.
// i3 = i1;
// i3 = i1 as I3;  // Ditto.
const i31: RawT<I1> = i1;

// `I4' has the same shape as `I1':
type I4 = RetaggedT<U3, 'A'>;
let i4: I4 = i3 as RawT<I3> as I4;
i4 = i1;
i1 = i4;
RawT

Extract raw type of tagged T. Distributes over unions.

Definition
type RawT<T> = T extends UniqueT<infer U, infer TTag_>
  ? U
  : T;
TagT

Extract tag from tagged T. Distributes over unions.

Definition
type TagT<T> = T extends UniqueT<infer U_, infer TTag>
  ? TTag
  : never;
RetaggedT

Retag a tagged T using tag TTag. Distributes over unions.

Definition
type RetaggedT<T, TTag extends PropertyKey> = T extends TaggedT<infer U, infer TTag_>
  ? TaggedT<U, TTag>
  : TaggedT<T, TTag>;

Logical operators

AndT

Logical "and" of T and U. Distributes over unions.

Definition
type AndT<T extends boolean, U extends boolean> = T extends false
  ? false
  : U extends false
    ? false
    : true;

NotT

Logical "not" of T. Distributes over unions.

Definition
type NotT<T extends boolean> = T extends false
  ? true
  : false;

OrT

Logical "or" of T and U. Distributes over unions.

Definition
type OrT<T extends boolean, U extends boolean> = T extends false
  ? U extends false
    ? false
    : true
  : true;

XorT

Logical "xor" of T and U. Distributes over unions.

Definition
type XorT<T extends boolean, U extends boolean> = T extends false
  ? U extends false
    ? false
    : true
  : U extends false
    ? true
    : false;

Miscellaneous utilities

NoDistributeT

Prevent distribution over T.

Definition
type NoDistributeT<T> = T extends any
  ? T
  : never;

NoInferT

Prevent type inference on T.

Definition
type NoInferT<T> = T & Pick<T, keyof T>;
Usage
declare const f1: <T>(i1: T, i2: T) => void;
f1({ p1: 'v1', p2: 'v2' }, { p1: 'v1' });  // An error sneaks in.

declare const f2: <T>(i1: T, i2: NoInferT<T>) => void;
// f2({ p1: 'v1', p2: 'v2' }, { p1: 'v1' });  // Causes compilation error.
f2({ p1: 'v1', p2: 'v2' }, { p1: 'v1', p2: 'v2' });

SelectT

Extract a member of a tagged union T using TTagKey as a tag property and TValue as its type.

Definition
type SelectT<T, TTagKey extends keyof T, TTagValue extends T[TTagKey]> = Extract<T, Record<TTagKey, TTagValue>>;
Usage
declare const TAG: unique symbol;
interface I1 {
  [TAG]: 'I1';
  p1: string;
}
interface I2 {
  [TAG]: 'I2';
  p1: number;
}
type I3 = I1 | I2;
type A11 = TaggedUnionMemberT<I3, typeof TAG, 'I1'>;  // Resolves to `I1'.