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

@detachhead/ts-helpers

v16.2.0

Published

various typescript helper functions and utility types

Downloads

1,878

Readme

ts-helpers

various typescript helper functions and utility types

npm

features

value tracking

this library includes many helper types and functions such as add, subtract, and substring which allow the values to be known at compile time

asdf

noUncheckedIndexedAccess support

the noUncheckedIndexedAccess compiler flag is epic, but there's room for improvement. for example, the following issue:

if (foo.length > 2) {
    const bar: string = foo[1] //error: string | undefined not assignable to string
}

can be solved with lengthGreaterThan

import { lengthGreaterThan } from '@detachhead/ts-helpers/dist/functions/Number'

if (lengthGreaterThan(foo, 2)) {
    const bar: string = foo[1] //no error, foo is casted to [string, string]
}

there's also lengthLessThan, lengthGreaterOrEqual, etc.

most of the array functions in this library keep track of the length, mostly thanks to this TupleOf utility type

date formatter type

this library contains a helper type and function for formatting dates using the date-fns format.

import { formatDate } from '@detachhead/ts-helpers/dist/functions/Date'

const date = formatDate(new Date(), 'dd-MM-yyyy')

assert(date === '01/01/2021') //compile error, wrong date format

you can use any date format that date-fns accepts, and the FormatDate utility type will generate a template literal type to match your desired date format.

Type Testing

With the exactly function you can test if types or values are an exact match to a type

import { exactly } from '@detachhead/ts-helpers/dist/functions/misc'

const a: 1 | 2 = 1
//values (also does a runtime assertion on the values)
exactly(1 as number, a) // error as `1 | 2` is not an exact match of `number`
exactly(1 as number, a as number) // no error
exactly(1 as 1 | 2, a) // no error

// mixed
exactly<number>()(a) // error as `1 | 2` is not an exact match of `number`
exactly<number>()(a as number) // no error
exactly<1 | 2>()(a) // no error

// types
type Foo = 1 | 2
exactly<1, Foo>() // error as `1 | 2` is not an exact match of `1`
exactly<1 | 2, Foo>() // no error

The Equals type allows you to check if two types are equal at the type level

import { Equals } from '@detachhead/ts-helpers/dist/types/misc'

type Foo = Equals<number, 1 | 2> // false
type Bar = Equals<any, 10> // false
type Baz = Equals<unknown, never> // false

variance modifier types

when using the old method syntax, typescript does not check the variance on assignment:

declare class A<T> {
    set(value: T): void
    get(): T
}

const a = new A<number>()

const b: A<unknown> = a

b.set('')
a.get() // typescript thinks this is a number but it's actually a string

for more information about how variance works, see this PR. the TL;DR is basically that arrow functions are checked more strictly than the old method syntax (for backwards compatibility reasons). this means you should be using arrow functions where possible.

declare class A<T> {
    set: (value: T) => void
    get: () => T
}

const a = new A<number>()

const b: A<unknown> = a // error: Type 'A<number>' is not assignable to type 'A<unknown>'

unfortunately however, arrow functions can't always be used. sometimes you need to use methods instead if, for example, you need to access super from a subclass:

class B extends A<number> {
    get = () => super.get() // runtime error, arrow functions can't access super
}

this is where variance modifiers come in

SafeVariance / ToArrowFunction

you can use SafeVariance<A> to enable strict variance checking on a class that has methods in it. or if for whatever reason you need to convert an individual function type to an arrow function type, you can use ToArrowFunction<A['get']>

import { SafeVariance, ToArrowFunction } from '@detachhead/ts-helpers/dist/types/Function'

class B<T> extends A<T> {
    override get() {
        return super.get()
    }
}

const a = new B<number>()

const b: SafeVariance<A<unknown>> = a // error

UnsafeVariance / ToNonArrowFunction

variance is only an issue when you're dealing with classes that have mutable state. if your type is immutable, you may want to disable variance checking without having to convert your shiny new arrow functions into cringe old methods.

to do this, simply use UnsafeVariance<A> on your class, or ToNonArrowFunction<A['set']> to convert a function type:

import { ToNonArrowFunction, UnsafeVariance } from '@detachhead/ts-helpers/dist/types/Function'

declare class A<T> {
    doSomethingElseThatTotallyDoesntChangeTheValue: (value: T) => void
    get: () => T
}

const a = new A<number>()

const b: UnsafeVariance<A<unknown>> = a // no error

drawbacks

it goes without saying that these modifiers do not change the runtime behavior of a function. an arrow function is still an arrow function regardless of whether you use the ToNonArrowFunction type on it.

casting functions

import { narrow, narrowCast, unsafeNarrow } from '@detachhead/ts-helpers/dist/functions/misc'

the as keyword doesn't always work exactly how you want. the narrow, unsafeNarrow and narrowCast functions can be used to cast variables in different ways

| | modifies original variable's type | returns the value with the casted type | intersects original type with casted type | allows non-overlapping types | | ----------------------- | --------------------------------- | -------------------------------------- | ----------------------------------------- | ---------------------------- | | as keyword | | yes | | | | narrow function | yes | | yes | | unsafeNarrow function | yes | | yes | yes | | narrowCast function | | yes | yes | yes |

requirements

typescript

since this package pushes the limits of the typescript compiler, i often update it to depend on unreleased versions of typescript for bug fixes and to ensure that upcoming releases won't break any of my wacky types. currently it depends on typescript >=5.0. you will probably encounter type errors and/or performance issues trying to use it with older versions.

runtime

as long as it supports es2021 you should be good. tested on:

  • nodejs >=15
  • browsers (chrome >=85)
  • deno (using esm.sh - eg. import { exactly } from 'http://esm.sh/@detachhead/ts-helpers/dist/utilityFunctions/misc')