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

@matt-usurp/grok

v1.1.0

Published

An expressive series of utilities for language like types

Downloads

9

Readme

Grok

An expressive series of utilities for language like types.

The meta programming within TypeScript using types can be very powerful and extremely helpful for enforcing strong types and safer builds. The goal of Grok is to remove some of the cognitive load that comes with trying to express these types by introducing a more verbose language syntax (as helpers).

Example

At core of Grok is an abstraction around the extends expression to introduce the concept of an if-statement. With only this Grok has grown to be extremely powerful and diverse in its offering.

In simple cases Grok might be considered over complicated but it really shines in complex type logic that changes depending on given inputs.

type MyValue<T> = (
  Grok.If<
    Grok.Value.IsExtending<T, 'foo'>,
    'its foo',
    Grok.If<
      Grok.Value.IsExtending<T, 'bar'>,
      'its bar',
      'its something'
    >,
  >
);
)

More logical helpers and value comparitors are available:

Logic & Expressions

  • Grok.If
  • Grok.And
  • Grok.Or
  • Grok.Not
  • Grok.Has

Type Helpers

  • Grok.Merge
  • Grok.Union
  • Grok.Union.FromArray
  • Grok.Union.RemoveValue
  • Grok.Union.Has
  • Grok.Record.RemoveValue
  • Grok.Record.ReplaceAny
  • Grok.Record.IsKeyOptional

Value Comparisons

  • Grok.Value.IsExtending
  • Grok.Value.IsExactly
  • Grok.Value.IsAny
  • Grok.Value.IsNever
  • Grok.Value.IsUnknown
  • Grok.Value.IsUndefined
  • Grok.Value.IsBoolean
  • Grok.Value.IsTrue
  • Grok.Value.IsFalse

Constraints

  • Grok.Constraint.ObjectLike
  • Grok.Constraint.FunctionLike
  • Grok.Constraint.ArrayWithOneOrMore<T>

Utility Helpers

  • Maybe to add undefined (opposite of NonNullable in typescript core)
  • Nullable to add null (opposite of NonNullable in typescript core)
  • Mutable to remove readonly (opposite of Readonly in typescript core)
  • Provider<T> to represent a function that returns its given value, alias () => T

Functional Helpers

  • noop() a function that has no-operation
  • never() a never assertion
  • okv() a key accessor
  • okvr() a key accessor with validation and requirements
  • okey() a type keyof assistance
  • union() a union value enforcement
  • provide() a helper for creating Provider<T>

Testing Helpers

  • fn()
  • instance()
  • partial() a Partial<T> to T disguise

Testing Helpers (types)

  • Grok.Assert for asserting values.
  • Grok.Assert.IsTrue for asserting a value is true.
  • Grok.Assert.IsFalse for asserting a value is false.

Documentation

Functional Helpers

A series of modular functional helpers and utilities are available also. These are all exported from the main entrypoint and as a modular path export that will allow for better tree shaking.

noop

A function that can be used to represent a no-operation.

never

For use with union exhaustiveness checking which will cause TypeScript to error when the given value is not of type never. This function simply throws an error of NeverReachAssertionError when compiled which should be caught by your error reporting tool of choice.

import { never } from '@matt-usurp/grok';
// or
import { never } from '@matt-usurp/grok/core/assert-never';

declare const union: 1 | 2

if (union === 1 || union === 2) {
  // do something
}

never(union);

Introducing a new value to union will cause never to raise an error at build time.

okv

An accessor utility for retreiving values from object sources by key. This is a factory that returns a function that can be called multiple times to retrieve values from the source by key.

There is a runtime safe version of this called okvr!

import { okv } from '@matt-usurp/grok';
// or
import { okv } from '@matt-usurp/grok/core/object';

declare const mapping: {
  readonly name: string;
  readonly age?: number;
}

okv(mapping)('name') // mapping.name [string]
okv(mapping)('age', 26) // mapping.age or 26 if undefined

okvr

A runtime safe version of okv() that will throw errors when keys are not available in the given source object.

import { okvr } from '@matt-usurp/grok';
// or
import { okvr } from '@matt-usurp/grok/core/object';

declare const mapping: {
  readonly name: string;
  readonly age?: number;
}

// mapping.name must not be undefined
okvr(mapping)('name')

// mapping.name will be replaced with fallback if undefined
// an error is thrown if fallback was undefined also.
okvr(mapping)('name', fallback)

// custom validator function is provided checking values are not null also
// mapping.age is verified, an error is thrown if its undefined or null (validator function)
okvr(mapping, ['age'], (v) => v !== null)

// mapping.age is verified, an error is thrown if its undefined
// mapping.name can be undefined, and fallback can be used.
okvr(mapping, ['age'])('name', fallback)

The okvr function is perfect for accessing keys against process.env when working in the context of Node.

const env = okvr(process.env);

env('SOME_AVAILABLE_VAR');
env('SOME_UNDEFINED_VAR', fallback);
env('ANOTHER_UNDEFINED_VAR'); // throws

okey

Allows for type-safe strings that are keys of an object. A functional variant of the <keyof SomeObject>'name' which cannot be used with JSX`.

import { okey } from '@matt-usurp/grok';
// or
import { okey } from '@matt-usurp/grok/core/object';

declare const mapping: {
  readonly name: string;
  readonly age?: number;
}

// the same
<keyof typeof mapping>'name';
okey<typeof mapping>('name');

union

A unique utility for times where you want to convert a union of strings to a string[] at runtime. This is done by forcing the values to be defined through a mapping that can be enforced at compile time. Unlike using MyUnion[] which does not enforce all values are present within the array.

import { union } from '@matt-usurp/grok';
// or
import { union } from '@matt-usurp/grok/core/value';

type MyUnion = 'name' | 'age';

const values = union<MyUnion>({
  name: undefined,
  age: undefined,
});

values; // ['name', 'age']

provide

A utility that creates functions that are compatible with a Provider<T>. A Provider<T> is a essentially a value wrapped in a function with no parameters. When called it will return the given value.

import { provide } from '@matt-usurp/grok'
// or
import { provide } from '@matt-usurp/grok/core/value';

const age = provide(30)

age(); // 30

Testing Helpers

A series of helpers and utlities for enriching your testing experience.

fn

An extension on vi.fn() that allows you to pass your function type as the generic and it will resolve the arguments and result for you.

import { fn } from '@matt-usurp/grok/testing';

type MyFunction = (age: number) => boolean;

const mock = fn<MyFunction>();

mock; // Mock<boolean, [age: number]>

expect(mock).toBeCalledTimes(0);

instance

A utiltity that disguises an object as the given type T. Optionally you can provide a string[] of functions and they will be automatically set using fn() above.

Note, this is a disguise and all properties are undefined unless set manually after calling. This function is inteded to minimise the amount of type casting and boiler plate needed for creating simplistic mocks of complex classes or types.

import { instance } from '@matt-usurp/grok/testing';

class Person {
  public readonly name: string;
  public readonly age: number;

  public speak(): void { .. };
  public walk(steps: number): boolean { .. };
};

const value = instance<Person>([
  'speak',
]);

value; // { speak: Mock }
value.speak(); // returns undefined

expect(value.speak).toBeCalledTimes(1);

partial

This is a utility that works similar to instance() but in a more simplified way, it can be better expressed through the type <T>(in: Partial<T>) => T. Again, this is intended for use with testing where a full T is needed but your test is asserting just a Partial<T>.

This is intended more of a utility around types and less about functionality.

import { partial } from '@matt-usurp/grok/testing';

type Person = {
  readonly name: string;
  readonly age: number;
  readonly gender: unknown;
}

const value = partial<Person>({
  name: 'Tony Stark',
});

value; // Person
value.name; // 'Tony Stark'
value.age; // undefined