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

@telokys/ts-meta-types

v2.1.3

Published

Type helpers for TypeScript

Downloads

5

Readme

ts-meta-types

Collection of useful TypeScript helpers for manipulating or altering types.

Install

npm install -D @telokys/ts-meta-types

Usage

import { ReplaceType } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second: boolean;
    third: string;
}

type MyNewData = ReplaceType<MyData, boolean, string>;
//=> interface MyNewData {
//       first: number;
//       second: string;
//       third: string;
//   }

API

Select keys from an interface

KeysOfType<Terface, Filter>

Source : KeysOfType.ts.

Will return a union of all Terface's keys of type Filter.

Example:

import { KeysOfType } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second: boolean;
    third: string;
    fourth: boolean;
}

type MyKeys = KeysOfType<MyData, boolean>;
//=> "second" | "fourth"

KeysWhereTypeCanBe<Terface, Filter>

Source : KeysWhereTypeCanBe.ts.

Returns a union of all Terface's keys for which Filter is assignable to the property.

Be careful: As opposed to KeysOfType<Terface, Filter> this WILL pick nullable properties EVEN IF undefined is not in Filter.
Adding undefined to Filter will pick ALL nullable properties!

Example:

import { KeysWhereTypeCanBe } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third: boolean;
    fourth: string;
    fifth: number | Date;
    sixth: string | Date;
    seventh?: Date;
}

type MyKeys = KeysWhereTypeCanBe<MyData, boolean | string>;
//=> "second" | "third" | "fourth" | "sixth"

// Be careful if you add undefined to Filter
type MyOtherKeys = KeysWhereTypeCanBe<MyData, boolean | string | undefined>;
//=> "second" | "third" | "fourth" | "sixth" | "seventh"

KeysNotOfType<Terface, Filter>

Source : KeysNotOfType.ts.

Will return a union of all Terface's keys NOT of type Filter.

Example:

import { KeysNotOfType } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second: boolean;
    third: string;
    fourth: boolean;
}

type MyKeys = KeysNotOfType<MyData, boolean>;
//=> "first" | "third"

KeysWhereTypeCannotBe<Terface, Filter>

Source : KeysWhereTypeCannotBe.ts.

Returns a union of all Terface's keys for which Filter is NOT assignable to the property. This helper is also aliased as KeysWhereTypeCantBe<Terface, Filter>.

Be careful: As opposed to KeysOfType<Terface, Filter> this WILL omit nullable properties EVEN IF undefined is not in Filter.
Adding undefined to Filter will omit ALL nullable properties!

Example:

import { KeysWhereTypeCannotBe } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third: boolean;
    fourth: string;
    fifth: number | Date;
    sixth: string | Date;
    seventh?: Date;
}

type MyKeys = KeysWhereTypeCannotBe<MyData, boolean | string>;
//=> "first" | "fifth" | "seventh"

// Be careful if you add undefined to Filter
type MyOtherKeys = KeysWhereTypeCannotBe<MyData, boolean | string | undefined>;
//=> "first" | "fifth" // Not "seventh" because it is nullable

Pick specific properties from an interface

PickMembers<Terface, K>

Source : PickMembers.ts.

Returns an interface containing the properties for which the key is specified in K.

Example:

import { PickMembers } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third?: string;
}

type MyNewData = PickMembers<MyData, "first" | "third">;
//=> interface MyNewData {
//       first: number;
//       third?: string;
//   }

PickMembersOfType<Terface, Filter>

Source : PickMembersOfType.ts.

Returns an interface containing the properties for which the value is assignable to Filter.

Be careful: this won't pick nullable properties if undefined is not in Filter. See PickMembersWhereTypeCanBe<Terface, Filter> if you don't want this behavior

Example:

import { PickMembersOfType } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third: boolean;
    fourth: string;
}

type MyNewData = PickMembersOfType<MyData, boolean | string>;
//=> interface MyNewData {
//       third: boolean;
//       fourth: string;
//   }

// Add undefined to the filter if you want to pick second
type MyOtherNewData = PickMembersOfType<MyData, boolean | string | undefined>;
//=> interface MyOtherNewData {
//       second?: boolean;
//       third: boolean;
//       fourth: string;
//   }

PickVoidMembers<Terface>

Source : PickMembersOfType.ts.

Returns an interface containing the properties for which the value is void.
This is a shortcut for PickMembersOfType<Terface, void>.

Example:

import { PickVoidMembers } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third: void;
    fourth: string;
}

type MyNewData = PickVoidMembers<MyData>;
//=> interface MyNewData {
//       third: void;
//   }

PickMembersWhereTypeCanBe<Terface, Filter>

Source : PickMembersWhereTypeCanBe.ts.

Returns an interface containing the properties for which Filter is assignable to the property.

Be careful: As opposed to PickMembersOfType<Terface, Filter> this WILL pick nullable properties EVEN IF undefined is not in Filter.
Adding undefined to Filter will pick ALL nullable properties!

Example:

import { PickMembersWhereTypeCanBe } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third: boolean;
    fourth: string;
    fifth?: number;
}

type MyNewData = PickMembersWhereTypeCanBe<MyData, boolean | string>;
//=> interface MyNewData {
//       second?: boolean; // Kept because can be boolean
//       third: boolean;
//       fourth: string;
//   }

// Be careful if you add undefined to Filter
type MyOtherNewData = PickMembersWhereTypeCanBe<MyData, boolean | string | undefined>;
//=> interface MyOtherNewData {
//       second?: boolean;
//       third: boolean;
//       fourth: string;
//       fifth?: number;    // Oops, was this expected?
//   }

PickMembersNotOfType<Terface, Filter>

Source : PickMembersNotOfType.ts.

Returns an interface containing the properties for which the value is NOT assignable to Filter.

Be careful: this WILL pick nullable properties if undefined is not in Filter.

Example:

import { PickMembersNotOfType } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third: boolean;
    fourth: string;
}

type MyNewData = PickMembersNotOfType<MyData, boolean | string>;
//=> interface MyNewData {
//       first: number;
//       second?: boolean; // Picked because undefined is not in Filter
//   }

// Add undefined to the filter if you don't want to pick second
type MyOtherNewData = PickMembersNotOfType<MyData, boolean | string | undefined>;
//=> interface MyOtherNewData {
//       first: number;
//   }

PickNonVoidMembers<Terface>

Source : PickMembersNotOfType.ts.

Returns an interface containing the properties for which the value is NOT void.
This is a shortcut for PickMembersNotOfType<Terface, void>.

Example:

import { PickNonVoidMembers } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third: void;
    fourth: string;
}

type MyNewData = PickNonVoidMembers<MyData>;
//=> interface MyNewData {
//       first: number;
//       second?: boolean;
//       fourth: string;
//   }

PickMembersWhereTypeCannotBe<Terface, Filter>

Source : PickMembersWhereTypeCannotBe.ts.

Returns an interface containing the properties for which Filter is NOT assignable to the value.
This helper is also aliased as PickMembersWhereTypeCantBe<Terface, Filter>.

Be careful: As opposed to PickMembersNotOfType<Terface, Filter> this WILL omit nullable properties EVEN IF undefined is not in Filter.
Adding undefined to Filter will omit ALL nullable properties!

Example:

import { PickMembersWhereTypeCannotBe } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third: boolean;
    fourth: string;
    fifth: number | Date;
    sixth: string | Date;
    seventh?: Date;
}

type MyNewData = PickMembersWhereTypeCannotBe<MyData, boolean | string>;
//=> interface MyNewData {
//       first: number;
//       fifth: number | Date;
//       seventh?: Date;
//   }

// Be careful if you add undefined to Filter
type MyOtherNewData = PickMembersWhereTypeCannotBe<MyData, boolean | string | undefined>;
//=> interface MyOtherNewData {
//       first: number;
//       fifth: number | Date;
//       // seventh is omitted because it is nullable
//   }

Modify an interface

ReplaceType<Terface, Filter, New>

Source : ReplaceType.ts.

Returns an interface where all properties assignable to Filter are now of type New.

Be careful: this won't replace nullable properties if undefined is not in Filter.

Example:

import { ReplaceType } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third: boolean;
    fourth: string;
}

type MyNewData = ReplaceType<MyData, boolean | string, number>;
//=> interface MyNewData {
//       first: number;
//       second?: boolean; // Not replaced : undefined is not in Filter
//       third: number;
//       fourth: number;
//   }

type MyOtherNewData = ReplaceType<MyData, boolean | string | undefined, number>;
//=> interface MyOtherNewData {
//       first: number;
//       second: number; // Replaced BUT NOT NULLABLE ANYMORE!
//       third: number;
//       fourth: number;
//   }

ReplaceTypeIfCanBe<Terface, Filter, New>

Source : ReplaceType.ts.

Returns an interface where all properties P for which Filter is assignable to P are now of type New.

Be careful: this will replace ALL nullable properties if undefined is in Filter.

Be careful: this is a strict replacement. Adding boolean to Filter will match boolean | number and replace it with New, not with New | number.

Example:

import { ReplaceTypeIfCanBe } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third: boolean;
    fourth: string;
    fifth: number | Date;
    sixth: string | Date;
    seventh?: Date;
}

type MyNewData = ReplaceTypeIfCanBe<MyData, boolean | string, number>;
//=> interface MyNewData {
//       first: number;
//       second: number;        // Strictly replaced : not nullable anymore
//       third: number;
//       fourth: number;
//       fifth: number | Date;
//       sixth: number;         // Strictly replaced : Can't be Date anymore
//       seventh?: Date;
//   }

// Adding undefined to the filter is dangerous: it will replace all nullable properties
type MyOtherNewData = ReplaceTypeIfCanBe<MyData, boolean | string | undefined, number>;
//=> interface MyOtherNewData {
//       first: number;
//       second: number;
//       third: number;
//       fourth: number;
//       fifth: number | Date;
//       sixth: number;
//       seventh: number;       // Oops! Didn't expect this one
//   }

MakeNonOptional<Terface, K>

Source : MakeNonOptional.ts.

Will return an interface where all properties in the union K are required. All properties not in the union K are left as is.
This helper will not recurse at all!

Example:

import { MakeNonOptional } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third?: string;
    deep?: {
        key: number;
        key2?: string;
    };
}

type MyNewData = MakeNonOptional<MyData, "second" | "deep">;
//=> interface MyNewData {
//       first: number;
//       second: boolean;     // Required
//       third?: string;      // Untouched : Not in K
//       deep: {              // Required
//           key: number;
//           key2?: string;   // Untouched : No recursion
//       };
//   }

MakeDeepNonOptional<Terface, K>

Source : MakeNonOptional.ts.

Will return an interface where all properties in the union K are required. All properties not in the union K are left as is.
If one of the properties specified in K is an interface, all its properties will recursively be marked as required as well.
This helper will recurse and mark everything down as required!

Example:

import { MakeDeepNonOptional } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    third?: string;
    deep?: {
        key: number;
        key2?: string;
        deepAgain?: {
            alpha: string;
            beta?: string;
        };
    };
}

type MyNewData = MakeDeepNonOptional<MyData, "second" | "deep">;
//=> interface MyNewData {
//       first: number;
//       second: boolean;        // Required
//       third?: string;         // Untouched : Not in K
//       deep: {                 // Required
//           key: number;
//           key2: string;       // Required by recursion
//           deepAgain: {        // Required by recursion
//               alpha: string;
//               beta: string;   // Required by recursion
//           };
//       };
//   }

Types

Scalar

Source : Scalar.ts.

Shortcut for string | number | boolean.

NullableScalar

Source : Scalar.ts.

Shortcut for Scalar | null.

OptionalScalar

Source : Scalar.ts.

Shortcut for Scalar | undefined.

OptionalNullableScalar

Source : Scalar.ts.

Shortcut for NullableScalar | undefined.

ObjectOf<T>

Source : ObjectOf.ts.

Shortcut for creating Records of type Record<string, T>.

Example:

import { ObjectOf } from "@telokys/ts-meta-types";

// Equivalent to Record<string, boolean>
type MyObject = ObjectOf<boolean>;
//=> {
//       [key: string]: boolean;
//   }

ValueOf<Terface>

Source : ValueOf.ts.

Returns a union containing the types of all values of Terface.

Example:

import { ValueOf } from "@telokys/ts-meta-types";

interface MyData {
    first: number;
    second?: boolean;
    duplicate: boolean;
    third?: string;
    deep?: {
        key: number;
        key2?: string;
        deepAgain?: {
            alpha: string;
            beta?: string;
        };
    };
}

type MyNewData = ValueOf<MyData>;
//=> string
//   | number
//   | boolean
//   | {
//       key: number;
//       key2?: string;
//       deepAgain?: {
//           alpha: string;
//           beta?: string;
//       };
//   }
//   | undefined

Misc

Debug<Terface>

Source : Debug.ts.

Taken from https://stackoverflow.com/a/57683652/4613742.

Will "clean" an interface in order for the intellisense to properly display the real computed type.

Be careful: This is not recursive.

Example:

Given the following code

import { Debug, MakeNonOptional, MakeDeepNonOptional } from "@telokys/ts-meta-types";

interface Test {
    test: boolean;
    test2?: number;
    test3: number;
    deep?: {
        tmp: string;
        tmp2?: string;
    }
}

type RawNonOptional = MakeNonOptional<Test>;
type RawNonOptionalDeep = MakeDeepNonOptional<Test>;

type DebuggedNonOptional = Debug<RawNonOptional>;
type DebuggedNonOptionalDeep = Debug<RawNonOptionalDeep>;

Here the intellisense given by VSCode for the first two types:

Debug_RawNonOptional Debug_RawNonOptionalDeep

As you can see, there are Required<> in someplaces. We have to mentally interpret them.
Do Required apply recursively? I don't want to remember, I want the intellisense to tell me the real type.

Wrapping the type in Debug will display the following:

Debug_DebuggedNonOptional Debug_DebuggedNonOptionalDeep

Now the intellisense is much more helpful. I can instantly see the updated version is doing what I hoped it would.

Note that the Debug helper is not recursive, as seen on the right image. If you want the recursive version, see DebugR<Terface>

DebugR<Terface>

Source : Debug.ts.

Taken from https://stackoverflow.com/a/57683652/4613742.

Will recursively "clean" an interface in order for the intellisense to properly display the real computed type.

Example:

Given the following code

import { DebugR, MakeNonOptional, MakeDeepNonOptional } from "@telokys/ts-meta-types";

interface Test {
    test: boolean;
    test2?: number;
    test3: number;
    deep?: {
        tmp: string;
        tmp2?: string;
    }
}

type RawNonOptional = MakeNonOptional<Test>;
type RawNonOptionalDeep = MakeDeepNonOptional<Test>;

type RecursivelyDebuggedNonOptional = DebugR<RawNonOptional>;
type RecursivelyDebuggedNonOptionalDeep = DebugR<RawNonOptionalDeep>;

Here the intellisense given by VSCode for the first two types:

Debug_RawNonOptional Debug_RawNonOptionalDeep

As you can see, there are Required<> in someplaces. We have to mentally interpret them.
Do Required apply recursively? I don't want to remember, I want the intellisense to tell me the real type.

Wrapping the type in DebugR will display the following:

Debug_RecursivelyDebuggedNonOptional Debug_RecursivelyDebuggedNonOptionalDeep

Now the intellisense is much more helpful. I can instantly see the updated version is doing what I hoped it would.