@toreda/strong-types
TypeScript icon, indicating that this package has built-in type declarations

0.28.5 • Public • Published

@toreda/strong-types

CI Coverage Quality Gate Status

Guaranteed types with validation in 1 line of code. Improve code quality & reliability while writing fewer lines of code.

What does it do?

import type {Int} from '@toreda/strong-types';
import {intMake} from '@toreda/strong-types';
//  int with initial value 10.
const int = intMake(10);
// Prints 10. It always return an int.
console.log(int());

// Set the value
int(11);
// Prints 11.
console.log(int());

// Won't set the value - it's not an int.
int(null);
int(undefined);
int(3.33);
int({});

// Prints 11
console.log(int());

Contents

  • Code Documentation
  • StrongType API
  • Data Types
    • Primary Types
      • StrongMap
      • StrongArray
      • Bool
        • Strict true or false values.
      • Dbl
        • Decimal values with arbitrary precision.
      • Float
        • Standard JavaScript number values with a StrongType wrapper.
      • Int
        • Positive & negative integers.
      • Text
        • String values
      • UInt
        • Unsigned integers.
    • Expressive Types
      • Email - string
        • Email address with format mailbox@domain.
      • Date - string
        • ISO standard date strings.
      • Id - string
        • string with configurable value restrictions.
      • HexColorCode - string
        • Any full or partial hex value representing a color code in RGB range (#000000 to #FFFFFF).
      • Port - unsigned integer
        • Port number in the range 1 to 65535.
      • OS - OS Value
        • Common OS platform names android, darwin, linux, and windows.
      • Size - {width: float; height: float}
        • Object with properties float x and float y.
      • SystemPort - unsigned integer
        • Port number in the eserved system port range 1 to 1024.
      • Time - string
        • ISO standard 12h or 24h time value.
      • Url - string
        • Any valid absolute Url according to RFC-3986.
      • Vec1 - {x: float}
        • Vector object with float validated property float x.
      • Vec2 - {x: float; y: float}
        • Vector object with float validated properties float x and float y.
      • Vec3 - {x: float; y: float; z: float}
        • Vector object with float validated properties float x, float y, and float z.
      • Vec4 - {x: float; y: float; z: float; w: float}
        • Vector object with float validated properties float x, float y, float z, and float w.
    • Examples
  • Conversion Functions
  • Custom Types
  • Package

 

StrongType API

All types in this package implement the StrongType interface which provide

General API

All Types

get(fallback: ValueT): ValueT

Get current value. The provided fallback is returned when StrongType has no current value. Always returns a type ValueT value.

getNull(): ValueT | null

Get and return current value if set, otherwise returns null. Useful when you need to know if there is a current value.

check(value?: ValueT): boolean

Check whether value is passes validation as type ValueT. Called by set(...) internally, but allows value validation before setting.

reset(): void

Reset current value to null. Useful for testing, Lamba environments, and object pools.

 

Numeric Types

Add add(input: ValueT): ValueT | null

Add input to value (value + input).

Returns

  • null when result value is not a valid ValueT.
    • ex: uint.add(-1) returns null when value is 0. 0 + -1 is -1 and not a valid UInt.
    • ex: int.add(1) returns `null

 

Subtract sub(input: ValueT): ValueT | null*

Subtract input from value (value - input).

Returns

  • null when result is not a valid ValueT.
    • ex: uint.sub(1) returns null when value is 0, because -1 is not a valid UInt.
  • result of subtraction when operation succeeds and result is a valid ValueT.

 

Multiply mul(input: ValueT): ValueT | null

Multiply value by input.

Returns

  • null if result of multiplication is not a valid ValueT.
  • 0 when either number is 0.

 

Divide div(input: ValueT): ValueT | null

Divide value by input.

Returns

  • null when result is not a valid ValueT
    • ex: uint.mul(-1) will always return null because UInt cannot be < 0.
  • result of divsion when operation succeeds.
  • 0 when either value or input is 0.
  • null when StrongType has no current value.

 

pow(n: ValueT): ValueT | null

Raise value to the nth power.

Returns

  • null when current value is null.
  • null when result value is too big, or too small for ValueT.
  • result of valueⁿ if result is a valid ValueT.

 

increment(): ValueT | null

Increment value by 1 if StrongType has a value. Returns null when increment is not successful.

Returns

  • null when result of value + 1 is not a valid ValueT.
  • null when StrongType has no value.
  • result when increment succeeds.

 

decrement(): ValueT | null

Decrease value by 1 if StrongType has a value. Returns null when decrement is not successful.

Returns

  • null when result of value - 1 is not a valid ValueT.
  • null when StrongType has no value.
  • result when decrement succeeds.

 

Data Types

StrongArray<T>

Strict Array type.

Accepts

  • Arrays matching type T provided to StrongArray<T> during init.

Rejects

  • Non-array values.

Make a StrongArray<T>

import type {StrongArray} from '@toreda/strong-types';
import {arrayMake} from '@toreda/strong-types';

// Create a new StrongArray of type string[].
// Fallback value is an empty array.
const arr = arrayMake<string>([]);

 

Bool

Strict boolean values.

 

Accepts

  • true
  • false

Rejects

  • Everything else (no type coercion).

 

Making Bool

import type {Bool} from '@toreda/strong-types';
import {boolMake} from '@toreda/strong-types';

// Create bool with fallback `false`.
// No initial value set.
const bool = boolMake(false);

 

Get Bool

Get the current value invoking the Bool object directly, calling bool.get(fallback), or bool.getNull().

 

Invoke Bool

All StrongType objects are also functions. Call the function without args to return the current value.

 

Create bool with fallback false & no initial value:

// Create bool with:
//	fallbackDefault		-	false
//	value				-	null (not provided)
const bool = boolMake(false);

// Prints 'false'
console.log(bool());

 

Create bool with value true & fallback false:

// Create bool with:
// 	fallbackDefault 	-	false
//	value				-	true
const bool = boolMake(false, true);

// Prints 'true'
// Second arg of boolMake is value.
console.log(bool());

 

Create bool with value false & fallback true:

// Create bool with:
//	fallbackDefault		-	true
//	value				-	false
const bool = boolMake(true, false);

// Prints 'false'.
console.log(bool());

 

Reset Bool

Reset any Bool object back to it's fallbackDefault value provided in boolMake(...).

const bool = boolMake(true);

// Set value to false
bool(false);

// Prints 'false'
console.log(bool());

// Reset object and remove current value.
// Object returns fallbackDefault 'true' until value is set.
bool.reset();

// Prints 'true', but bool has no current value.
console.log(bool());

 

Int

Positive & negative Integers stored as a JavaScript number. No type coercion used.

 

Values

Accepts

  • Integers in range: Number.MIN_SAFE_INT to Number.MAX_SAFE_INT (inclusive).

Rejects

  • Non-integers values.
  • Values with decimal places (4.44, 0.11, etc).

 

Make Int

With number

import type {Int} from '@toreda/strong-types';
import intMake from '@toreda/strong-types';

const value = intMake(0, 444111);

 

Reset Int

const int = intMake(0);

// Set value to 101.
int(101);

// Prints 101
console.log(int());

// Reset object and remove current value.
// Returns fallbackDefault (0) until value is set.
int.reset();

// Prints 0. Int has no value.
console.log(int());
const int = intMake(10);
// Set value to 100.
int(100);

// Prints 100.
console.log(log());
int.reset();

// Prints 10. Value null & fallback returned instead.
console.log(int());

// Prints null - value is null. getNull() does not use fallback.
console.log(int.getNull());

UInt

Unsigned Integers stored as a JavaScript number.

 

Values

Accepts

  • Rejects NaN
  • Rejects negative integers (e.g. -22).
  • Positive Integers from 0 to Number.MAX_SAFE_INT (inclusive).

Rejects

  • NaN
  • Non-finite values Number.POSITIVE_INFINITY and Number.NEGATIVE_INFINITY.
  • Negative Integers.
    • ex: -10, -1
  • Positive & negative decimals. - ex: 5.1, 100.9, -1.1, -99.99, 0.11, -0.099

 

Make UInt

From number:

import type {UInt} from '@toreda/strong-types';
import uIntMake from '@toreda/strong-types';

const value = uIntMake(0, 444111);

 

Dbl

Decimal values supporting arbitrary precision.

 

Values

Accepts

  • strings containing arbitrarily large positive or negative decimal & integer values. Numeric values for Dbl in string form may exceed Number.MAX_VALUE and Number.MAX_SAFE_INT.
    • ex: '1', '-100', '1.1111111', '0.00009', '1.000009', '-99.0009'
  • numbers from Number.MIN_VALUE to Number.MAX_VALUE (inclusive).
    • Note: Represent numbers exceeding Number.MAX_VALUE or below Number.MIN_VALUE as string or Big.

Rejects

  • Non-finite values Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY.

 

Make Dbl

From number:

import type {Dbl} from '@toreda/strong-types';
import dblMake from '@toreda/strong-types';

const value = dblMake(0, 1111187);

From string:

import type {Dbl} from '@toreda/strong-types';
import dblMake from '@toreda/strong-types';

const value = dblMake(0, '1081987419714971411.441');

From Big:

import Big from 'big.js';
import type {Dbl} from '@toreda/strong-types';
import dblMake from '@toreda/strong-types';

const value = dblMake(0, Big(8714817418741));

 

Examples

Each built-in type exports a type and make function. The below examples use Int but work the same using: StrongArray, Bool, Dbl, Float, Int, Text, and UInt.

Instantiate with initial value

import {Int, intMake} from '@toreda/strong-types';

const initial = 11;
const fallback = 55;
const int = intMake(initial, fallback);

// Returns 11 - initial value was 11.
const value = int();

Instantiate without initial value

import {Int, intMake} from '@toreda/strong-types';

const fallback = 919;
const int = intMake(null, fallback);

// value is 919 - initial value was null, so fallback was
// returned instead to maintain the function's return type guarantee.
const value = int();

Get with Fallback

  • get(fallback: T): T Call container.get(fallback) when a per-call fallback is preferred instead of the container's default fallback.
import {Int, intMake} from '@toreda/strong-types';
const int = intMake(null, 555);

const fallback = 331;
// Prints 331 (fallback) instead of 555 (container default fallback).
console.log(value.get(fallback));

GetNull

  • getNull(): T | null Call container.getNull() to the current value, even if null. Value will never be undefined and will always return either null, or a value of container's generic type T.

NOTE: getNull DOES NOT take a fallback argument and will not return the container's default fallback. It always returns value (null or StrongType<T>).

import {Int, intMake} from '@toreda/strong-types';

const fallback = 919;
const int = intMake(null, fallback);

// Prints null. Default fallback is not used for `getNull` calls.
console.log(int.getNull());

Set Value

import type {Int} from '@toreda/strong-types';
import {intMake} from '@toreda/strong-types';

const initial = 331;
const fallback = 400;
const int = intMake(initial, fallback);

// value is 331 - the int's initial value.
const value = int();

// Set int to a new value.
int(555);

// value is 555 - the value we updated int to.
const value = int();

Set null

import {Int, intMake} from '@toreda/strong-types';

const initial = 414;
const fallback = 500;
const int = intMake(initial, fallback);

// value is 414 - the int's initial value.
const value = int();


// Set value to null.
int(null);

// value is 500 - Fallback returned because value was null.
const value = int();

Reset Value

Call myContainer.reset() to reset value without creating a new StrongType container. Default Fallback will not be reset. Useful for unit testing and serverless environments where the previous container value or state is unknown.

import {Int, intMake} from '@toreda/strong-types';

const initial = 515;
const fallback = 600;
const int = intMake(initial, fallback);

// value is 515 (the initial value).
const value = int();

// Reset container value
int.reset();

// Prints 600 (fallback). value was reset to null,
// fallback was returned to maintain return type guarantee.
console.log(int());

 

Validation

StrongType containers validate value inputs before setting. Bad values are ignored and will not cause a throw. Each built-in container type provides specific guarantees for which values are allowed.

import {Int, intMake} from '@toreda/strong-types';
const int = intMake(50, 100);

// success is false.
// container.value is still it's initial value 50 because 1.5 is not an int.
// Int does not round or truncate non-integers. They are simply ignored.
const success = int(1.5);

 

StrongMap

Creating and using a StrongMap class.

import {StrongMap, Int, Text, intMake, textMake} from '@toreda/strong-types';


export class SomeConfig extends StrongMap {
	public readonly counter: Int;
	public readonly name: Text;

	constructor(json: any) {
		super();
		this.counter = intMake(0, 0);
		this.name = textMake('', 'TreeBeard');
		this.parse(json);
	}
}


// Use it
const myConfig = new SomeConfig();

// Prints '0'
console.log(myConfig.counter());

// Prints 'Treebeard'
console.log(myConfig.name());

Creating a StrongMap and loading values from JSON

import {StrongMap, StringInt, Text, intMake, textMake} from '@toreda/strong-types';

export class SomeConfig extends StrongMap {
	public readonly counter: Int;
	public readonly name: Text;

	constructor(json?: any) {
		super();
		this.counter = intMake(0, 0);
		this.name = textMake(null, 'TreeBeard');
		this.parse(json);
	}
}

const myJSON = {
	'counter': 99,
	'name': 'Sauron'
};

// Load the recursively parse a JSON object.
const myConfig = new SomeConfig(myJSON);

// Prints 99 - myJSON.counter was loaded into SomeConfig.counter at instantiation.
console.log(myConfig.counter());

// Prints 'Sauron' - myJSON.name was loaded into SomeConfig.name at instantiation.
console.log(myConfig.name());

Converting a StrongMap to a json object

import {StrongMap, StringInt, Text, intMake, textMake} from '@toreda/strong-types';

export class SomeConfig extends StrongMap {
	public readonly counter: Int;
	public readonly name: Text;

	constructor(json?: any) {
		super();
		this.counter = intMake(0, 0);
		this.name = textMake(null, 'TreeBeard');
		this.parse(json);
	}
}

const myJSON = {
	'counter': 99,
	'name': 'Sauron'
};

// Create the StrongMap with myJSON data
const myConfig = new SomeConfig(myJSON);

// Change a value in the StrongMap
myConfig.name('Gandalf');

// {counter: 99, name: 'Gandalf'}
const configAsJSON = myConfig.jsonify();

 

 

Validators

 

Custom Types

Each built-in type like Int and UInt are helper functions wrapping Strong<T>. They also apply validators which guarantee the Strong<T> value behaves as expected. While built-ins are provided for convenience, you can create custom types with your own validators.

Instantiate Strong<T>

import {Strong, strongMake} from '@toreda/strong-types';

export type MyOwnType = {
	id: string | null;
	name: string | null;
};

const initial: MyOwnType = {
	id: 'hello',
	name: 'my name is'
};

const fallback: MyOwnType = {
	id: null,
	name: null
};

const myObj = strongMake<MyOwnType>(initial, fallback);

 

Install

Install @toreda/strong-types directly from NPM or clone the Github repo.

Install using Yarn (preferred)

  1. Open a shell (or console).
  2. Navigate to the the StrongTypes root project folder.
  3. Enter the following commands in order. Wait for each to complete before typing the next.
yarn

Install using NPM

  1. Open a shell (or console).
  2. Navigate to the the StrongTypes root project folder.
  3. Enter the following commands in order. Wait for each to complete before typing the next.
npm install

Run Unit Tests

Install or clone StrongTypes (see above).

StrongTypes tests are written with Jest which is also a project dev dependency.

Installing jest is not required after project dependencies are installed (see above).

yarn test

Build from source

The next steps are the same whether you installed the package using NPM or cloned the repo from Github.

Build with Yarn

Enter the following commands in order from the StrongTypes root project folder.

yarn build

Build with NPM

Enter the following commands in order from the StrongTypes root project folder.

npm run-script build

 

Legal

License

MIT © Toreda, Inc.

 

Copyright

Copyright © 2019 - 2021 Toreda, Inc. All Rights Reserved.

https://www.toreda.com

Package Sidebar

Install

npm i @toreda/strong-types

Weekly Downloads

1

Version

0.28.5

License

MIT

Unpacked Size

1.53 MB

Total Files

825

Last publish

Collaborators

  • mbrich
  • saxan