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

@uplift-ltd/ts-helpers

v3.0.0

Published

Helpers for dealing with typescript.

Downloads

1,292

Readme

@uplift-ltd/ts-helpers

Installation

npm i --save @uplift-ltd/ts-helpers

API

assertUnreachable

Invoke this assertion for an unreachable case.

import { assertUnreachable } from "@uplift-ltd/ts-helpers";

switch (condition) {
  case true:
    return bleh;
  default:
    assertUnreachable("invalid condition");
}

notEmpty

Filter and array so typescript knows there are no null or undefined values.

import { notEmpty } from "@uplift-ltd/ts-helpers";

const array: (string | null)[] = ["foo", "bar", null, "zoo", null];
const filteredArray: string[] = array.filter(notEmpty);

typedIncludes

Assert whether a variable is a member of an array in a type-safe way. This also avoids the "string" is not a member of TYPE errors.

const colors = ["blue", "green", "red"] as const;

// You avoid the error here, that myColor is string, not a member of colors
if (typedIncludes(colors, myColor)) {
  // typeof myColor = "blue" | "green" | "red"

  // You also get a type error here that yellow is not "blue" | "green" | "red"
  if (myColor === "yellow") {
  }
}

ArrayElement

Returns the type of an element of the array

type Item = ArrayElement<string[]>; // => string
type Item = ArrayElement<(ThisLineItem | ThatLineItem)[]>; // => (ThisLineItem | ThatLineItem)

Arrays

Ensures that the provided data is an array, and if it's not, wraps it in an array

type Item = ThisLineItem | ThisLineItem[];
const itemOrItems: Item;
const itemsArray: ThisLineItem[] = ensureArray(itemOrItems);

ArrayToUnion

Converts an array of strings into a discriminated type union.

const httpMethods = ["GET", "POST", "PUT", "PATCH", "OPTIONS", "HEAD", "DELETE"] as const; // note: `as const` is required
type HttpMethod = ArrayToUnion<typeof httpMethods>; // => "GET" | "POST" | "PUT" | "PATCH" | "OPTIONS" | "HEAD" | "DELETE"

DeepPartial

Deeply marks attributes as optional

interface RequiredFields {
  firstName: string;
  lastName: string;
  age: number;
  address: {
    street: string;
    postalCode: string;
    city: string;
    state: string;
    country: string;
  };
}

type OptionalFields = DeepPartial<RequiredFields>;
/*
 * => {
 *   firstName?: string;
 *   lastName?: string;
 *   age?: number;
 *   address?: {
 *     street?: string;
 *     postalCode?: string;
 *     city?: string;
 *     state?: string;
 *     country?: string;
 *   }
 * }
 *
 */

RequireAtLeastOne

Tell typescript to require at least one of the keys to be present.

import { RequireAtLeastOne } from "@uplift-ltd/ts-helpers";

interface Props {
    a?: boolean
    b?: boolean
    c: boolean
}

type ABProps = RequireAtLeastOne<Props, 'a' | 'b'>

<Component a c /> /* passes */
<Component b c /> /* passes */
<Component a b c /> /* passes */
<Component c /> /* throws */

RequireOnlyOne

Tell typescript to require only one (not all) of the keys to be present.

import { RequireOnlyOne } from "@uplift-ltd/ts-helpers";

interface Props {
    a?: boolean
    b?: boolean
    c: boolean
}

type ABProps = RequireOnlyOne<Props, 'a' | 'b'>

<Component a c /> /* passes */
<Component b c /> /* passes */
<Component a b c /> /* throws */
<Component c /> /* throws */

Unpromise

Returns the result type of a promise.

type Result = Unpromise<Promise<boolean>>; // => boolean

Can be combined with ReturnType to get the result of a function that returns a promise.

type TheTypeWeWant = { a: boolean };

type PromiseReturningFunction = () => Promise<TheTypeWeWant>;

type TheTypeWeHave = Unpromise<ReturnType<PromiseReturningFunction>>;

// TheTypeWeHave is now TheTypeWeWant

UnreachableCaseError

Throw this type of error for an unreachable case.

import { UnreachableCaseError } from "@uplift-ltd/ts-helpers";

switch (condition) {
  case true:
    return bleh;
  default:
    throw new UnreachableCaseError("invalid condition");
}

ValuesOf

Returns a type union of the values of a record/object

const Colors = {
  BLUE: "blue",
  RED: "red",
  GREEN: "green",
};

type Color = ValuesOf<typeof Colors>; // => "blue" | "red" | "green"

Relay

Helpers for working with Relay Connections

GetConnectionNode
Extracts the Node from a Relay Connection, even if some or all of the Connection is nullable

GetConnectionNodeArray
Helper that just returns an array of the Connection Node, also works if Connection is nullable

type User = {
  firstName: string;
  lastName: string;
  age: number;
};

// Non-nullable
type Organization = {
  users: {
    edges: { node: User }[];
  };
};

// Nullable
type NullableOrganization = {
  users?: {
    edges?: { node: User }[] | null;
  } | null;
};

Organization["users"]["edges"][0]["node"];
// => User

GetConnectionNode<Organization["users"]>;
// => User

GetConnectionNodeArray<Organization["users"]>;
// => Array<User>

GetConnectionNode<NonNullable<NullableOrganization["users"]>>;
// => User

GetConnectionNodeArray<NonNullable<NullableOrganization["users"]>>;
// => Array<User>

makeUnionMemberGuard

Filter on a discriminated union.

import { makeGraphqlUnionGuard, makeUnionMemberGuard } from "@uplift-ltd/ts-helpers";

type A = {
  __typename: "A";
  x: number;
};

type B = {
  __typename: "B";
  y: number;
};

type AB = A | B;

const a = { __typename: "A", x: 1 } as const;
const b = { __typename: "B", y: 2 } as const;

const ab: AB[] = [a, b];

ab.filter(makeUnionMemberGuard("__typename", "A")); // A[]

ab.filter(makeUnionMemberGuard("__typename", "B")); // B[]

ab.filter(makeGraphqlUnionMemberGuard("A")); // A[]

ab.filter(makeGraphqlUnionMemberGuard("B")); // B[]