# @matt-usurp/grok

> An expressive series of utilities for language like types

Latest version **1.1.0** (published 2022-11-30) · GPL-3.0-or-later license · 0 weekly downloads

## Install

```sh
npm install @matt-usurp/grok
pnpm add @matt-usurp/grok
yarn add @matt-usurp/grok
bun add @matt-usurp/grok
```

## Health

**Score 20/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.1.0 |
| Published | 2022-11-30 |
| First published | 2022-01-02 |
| Weekly downloads | 0 |
| License | GPL-3.0-or-later |
| TypeScript types | bundled |
| Module format | CommonJS |
| Node | >=16.12.0 |
| Dependencies | 1 |
| Unpacked size | 44.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1 |
| Maintainers | matt-usurp |
| Keywords | typescript, type, utitility, meta, language, assert, testing |

## Links

- npm: https://www.npmjs.com/package/@matt-usurp/grok
- Repository: https://github.com/matt-usurp/grok
- Homepage: https://github.com/matt-usurp/grok#readme
- Issues: https://github.com/matt-usurp/grok/issues
- npm.io page: https://npm.io/package/@matt-usurp/grok

## Dependencies (1)

- [tslib](https://npm.io/package/tslib.md) ^2.4.1

## Alternatives

- [duck](https://npm.io/package/duck.md) — 4.2M weekly downloads
- [ava](https://npm.io/package/ava.md) — 560.2K weekly downloads
- [storybook-addon-module-mock](https://npm.io/package/storybook-addon-module-mock.md) — 71.7K weekly downloads
- [vest](https://npm.io/package/vest.md) — 50.1K weekly downloads
- [@ethereum-waffle/mock-contract](https://npm.io/package/@ethereum-waffle/mock-contract.md) — 40.0K weekly downloads

## Recent versions

- 1.1.0 (latest) — 2022-11-30
- 0.8.7 (next) — 2022-09-21
- 1.0.1 — 2022-10-09
- 1.0.0 — 2022-10-09
- 0.8.6 — 2022-09-21
- 0.8.5 — 2022-09-15
- 0.8.4 — 2022-09-15
- 0.8.3 — 2022-09-15
- 0.8.2 — 2022-09-14
- 0.8.1 — 2022-09-14
- 0.8.0 — 2022-09-14
- 0.7.1 — 2022-06-10
- 0.7.0 — 2022-06-10
- 0.7.0-rc.1 — 2022-06-07
- 0.6.4 — 2022-05-25
- … 17 more at https://npm.io/package/@matt-usurp/grok/versions

## 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.

```ts
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](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#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.

```ts
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`!

```ts
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.

```ts
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.

```ts
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`.

```ts
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.

```ts
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.

```ts
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.

```ts
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.

```ts
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.

```ts
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
```

---
_Source: https://npm.io/package/@matt-usurp/grok · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
