@bedard/utils v0.30.1
@bedard/utils
This repository acts as my own personal lodash. It contains a number of utility types and functions that I found myself duplicating between projects. I do not anticipate breaking changes, but I'm also not ruling it out. Upgrade with caution.
Installation
The recommended installation method is via NPM.
npm install @bedard/utils
Alternatively, the functions maybe be accessed via a CDN. When using the CDN, the library will be exposed globally as BedardUtils
.
<script src="https://unpkg.com/@bedard/utils"></script>
Functions
Animation
createEasingFunction
easeInSine
easeOutSine
easeInOutSine
easeInQuad
easeOutQuad
easeInOutQuad
easeInCubic
easeOutCubic
easeInOutCubic
easeInQuart
easeOutQuart
easeInOutQuart
easeInQuint
easeOutQuint
easeInOutQuint
easeInExpo
easeOutExpo
easeInOutExpo
easeInCirc
easeOutCirc
easeInOutCirc
easeInBack
easeOutBack
easeInOutBack
easeInElastic
easeOutElastic
easeInOutElastic
easeInBounce
easeOutBounce
easeInOutBounce
Color
Math
addVectors
angleFrom
bilerp
cols
degreesToRadians
flattenCols
flattenRows
flip
intersect
isEven
lerp
lerpVectors
measure
polygon
radiansToDegrees
roll
rotateMatrix
rotateVector
rows
scale
slope
Utility
addVectors
Add vectors together.
import { addVectors } from '@bedard/utils'
addVectors([1, 2], [3, 4]) // [4, 6]
angleFrom
Calculate angled distance from a vector. An angle of 0
degrees will track along the X axis, with positive angles rotating counter-clockwise.
import { angleFrom } from '@bedard/utils'
angleFrom([0, 0], 90, 1) // [0, 1] (approximate)
bilerp
Bi-linear interpolation between vectors.
import { bilerp } from '@bedard/utils'
bilerp([0, 0], [10, 10], 0.5) // [5, 5]
cols
Chunk a square matrix into columns. Note that the source matrix must be provided in row-major order.
import { cols } from '@bedard/utils'
cols([
0, 1, 2,
3, 4, 5,
6, 7, 8,
]) // [[0, 3, 6], [1, 4, 7], [2, 5, 8]]
createEasingFunction
Create an easing function from cubic-bezier points. Note that the included easing functions do not use this utility. They are simpler mathematical functions, and do not produce quite the same results as easing functions created using this utility.
import { createEasingFunction } from '@bedard/utils'
const linear = createEasingFunction(0, 0, 1, 1)
linear(0.5) // 0.5
deepEqual
Deep object comparison.
import { deepEqual } from '@bedard/utils'
deepEqual({ foo: { bar: 1 }}, { foo: { bar: 1 }}) // true
degreesToRadians
Convert degrees to radians.
import { degreesToRadians } from '@bedard/utils'
degreesToRadians(180) // 3.141592653589793
easeInSine
Easing function that follows this curve.
import { easeInSine } from '@bedard/utils'
easeInSine(0.5) // 0.2928932188134524
easeOutSine
Easing function that follows this curve.
import { easeOutSine } from '@bedard/utils'
easeOutSine(0.5) // 0.7071067811865475
easeInOutSine
Easing function that follows this curve.
import { easeInOutSine } from '@bedard/utils'
easeInOutSine(0.5) // 0.49999999999999994
easeInQuad
Easing function that follows this curve.
import { easeInQuad } from '@bedard/utils'
easeInQuad(0.5) // 0.25
easeOutQuad
Easing function that follows this curve.
import { easeOutQuad } from '@bedard/utils'
easeOutQuad(0.5) // 0.75
easeInOutQuad
Easing function that follows this curve.
import { easeInOutQuad } from '@bedard/utils'
easeInOutQuad(0.5) // 0.5
easeInCubic
Easing function that follows this curve.
import { easeInCubic } from '@bedard/utils'
easeInCubic(0.5) // 0.125
easeOutCubic
Easing function that follows this curve.
import { easeOutCubic } from '@bedard/utils'
easeOutCubic(0.5) // 0.875
easeInOutCubic
Easing function that follows this curve.
import { easeInOutCubic } from '@bedard/utils'
easeInOutCubic(0.5) // 0.5
easeInQuart
Easing function that follows this curve.
import { easeInQuart } from '@bedard/utils'
easeInQuart(0.5) // 0.0625
easeOutQuart
Easing function that follows this curve.
import { easeOutQuart } from '@bedard/utils'
easeOutQuart(0.5) // 0.9375
easeInOutQuart
Easing function that follows this curve.
import { easeInOutQuart } from '@bedard/utils'
easeInOutQuart(0.5) // 0.5
easeInQuint
Easing function that follows this curve.
import { easeInQuint } from '@bedard/utils'
easeInQuint(0.5) // 0.03125
easeOutQuint
Easing function that follows this curve.
import { easeOutQuint } from '@bedard/utils'
easeOutQuint(0.5) // 0.96875
easeInOutQuint
Easing function that follows this curve.
import { easeInOutQuint } from '@bedard/utils'
easeInOutQuint(0.5) // 0.5
easeInExpo
Easing function that follows this curve.
import { easeInExpo } from '@bedard/utils'
easeInExpo(0.5) // 0.03125
easeOutExpo
Easing function that follows this curve.
import { easeOutExpo } from '@bedard/utils'
easeOutExpo(0.5) // 0.96875
easeInOutExpo
Easing function that follows this curve.
import { easeInOutExpo } from '@bedard/utils'
easeInOutExpo(0.5) // 0.5
easeInCirc
Easing function that follows this curve.
import { easeInCirc } from '@bedard/utils'
easeInCirc(0.5) // 0.1339745962155614
easeOutCirc
Easing function that follows this curve.
import { easeOutCirc } from '@bedard/utils'
easeOutCirc(0.5) // 0.8660254037844386
easeInOutCirc
Easing function that follows this curve.
import { easeInOutCirc } from '@bedard/utils'
easeInOutCirc(0.5) // 0.5
easeInBack
Easing function that follows this curve.
import { easeInBack } from '@bedard/utils'
easeInBack(0.5) // -0.08769750000000004
easeOutBack
Easing function that follows this curve.
import { easeOutBack } from '@bedard/utils'
easeOutBack(0.5) // 1.0876975
easeInOutBack
Easing function that follows this curve.
import { easeInOutBack } from '@bedard/utils'
easeInOutBack(0.5) // 0.5
easeInElastic
Easing function that creates an elastic-in effect.
import { easeInElastic } from '@bedard/utils'
easeInElastic(0.5) // -0.015625000000000045
easeOutElastic
Easing function that creates an elastic-out effect.
import { easeOutElastic } from '@bedard/utils'
easeOutElastic(0.5) // 1.015625
easeInOutElastic
Easing function that creates an elastic-in-out effect.
import { easeInOutElastic } from '@bedard/utils'
easeInOutElastic(0.5) // 0.5
easeInBounce
Easing function that creates a bounce-in effect.
import { easeInBounce } from '@bedard/utils'
easeInBounce(0.5) // 0.234375
easeOutBounce
Easing function that creates a bounce-out effect.
import { easeOutBounce } from '@bedard/utils'
easeOutBounce(0.5) // 0.765625
easeInOutBounce
Easing function that creates a bounce-in-out effect.
import { easeInOutBounce } from '@bedard/utils'
easeInOutBounce(0.5) // 0.5
entries
Type safe wrapper around Object.entries
import { entries } from '@bedard/utils'
entries({ foo: 'bar' }) // [['foo', 'bar']]
flattenCols
Flatten an array of columns to a matrix in row-major order.
import { flattenCols } from '@bedard/utils'
flattenCols([
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
]) // [0, 1, 2, 3, 4, 5, 6, 7, 8]
flattenRows
Flatten an array of rows to a matrix in row-major order.
import { flattenRows } from '@bedard/utils'
flattenRows([
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
]) // [0, 1, 2, 3, 4, 5, 6, 7, 8]
flip
Convert between rows and columns. A good way to visualize this operation is holding a card by the top-left and bottom-right corners and flipping it over.
import { flip } from '@bedard/utils'
flip([
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
]) // [[0, 3, 6], [1, 4, 7], [2, 5, 8]]
hslToRgb
Convert [hue, saturation, lightness, alpha?]
to [red, green, blue, alpha]
values.
import { hslToRgb } from '@bedard/utils'
hslToRgb([0, 1, 0.5]) // [255, 0, 0, 1]
intersect
Intersect two-dimensional lines. Returns undefined
if lines are parellel.
import { intersect } from '@bedard/utils'
intersect([[-1, 0], [1, 0]], [[0, 1], [0, -1]]) // [0, 0]
isEmail
A fairly permissive email test where the value must be shaped email@domain.tld
, and contain exactly one @
characters.
import { isEmail } from '@bedard/utils'
isEmail('hello@world.com') // true
isEven
Test if a number is even.
import { isEven } from '@bedard/utils'
isEven(2) // true
keys
Type-safe wrapper around Object.keys
import { keys } from '@bedard/utils'
keys({ foo: 'bar' }) // ['foo']
lerp
Linear interpolation between numbers.
import { lerp } from '@bedard/utils'
lerp(0, 10, 0.5) // 5
lerpColors
Linear interpolation between colors.
import { lerpColors } from '@bedard/utils'
lerpColors('#000000', '#ffffff') // '#808080'
lerpVectors
Linear interpolation between two vectors. This function is similar to bilerp
, but for vectors of any size, or even vectors of different sizes.
import { lerpVectors } from '@bedard/utils'
lerpVectors([0, 0, 0], [1, 2, 3], 0.5) // [0.5, 1, 1.5]
measure
Measure the distance between two vectors.
import { measure } from '@bedard/utils'
// arguments can be provided as a pair of vectors
measure([0, 0], [3, 4]) // 5
// or as a single line argument
measure([[0, 0], [3, 4]]) // 5
parse
A type-safe wrapper around JSON.parse
. This utility is complimented by stringify
, Json
, and UnwrapJson
.
import { stringify } from '@bedard/utils'
stringify({ foo: 'bar' }) // '{"foo":"bar"}' as Json<{ foo: string }>
parseColor
Parse an RGB string to [red, green, blue, alpha]
values. An error will be thrown if the value is not valid.
import { parseColor } from '@bedard/utils'
parseColor('#123456') // [18, 52, 86, 0]
polygon
Create a regular polygon. The first argument defines the number of points, with the second defining the circumradius. Points start from the 12 o'clock position, and rotate counter-clockwise around the origin.
import { polygon } from '@bedard/utils'
polygon(4, 1) // [[0, 1], [-1, 0], [0, -1], [1, 0]] (approximate)
radiansToDegrees
Convert radians to degrees.
import { radiansToDegrees } from '@bedard/utils'
radiansToDegrees(Math.PI) // 180
roll
Roll the start of an array forwards or backwards.
import { roll } from '@bedard/utils'
roll([0, 1, 2], 1) // [1, 2, 0]
rgbToHsl
Convert [red, green, blue, alpha?]
to [hue, saturation, lightness, alpha]
values.
import { rgbToHsl } from '@bedard/utils'
rgbToHsl([255, 0, 0]) // [0, 1, 0.5, 1]
rotateMatrix
Rotate a square matrix. Positive values apply clockwise rotations.
import { rotateMatrix } from '@bedard/utils'
rotateMatrix([
0, 1, 2,
3, 4, 5,
6, 7, 8,
], 1) // [6, 3, 0, 7, 4, 1, 8, 5, 2]
rotateVector
Rotate a vector counter-clockwise around the origin.
import { rotateVector } from '@bedard/utils'
rotateVector([0, 1], 90) // [-1, 0] (approximate)
rows
Chunk a square matrix into rows. Note that the source matrix must be provided in row-major order.
import { rows } from '@bedard/utils'
rows([
0, 1, 2,
3, 4, 5,
6, 7, 8,
]) // [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
scale
Multiple a vector by a number.
import { scale } from '@bedard/utils'
scale([1, 2], 2) // [2, 4]
slope
Calculate the slope of a line.
import { slope } from '@bedard/utils'
// arguments can be provided as a pair of vectors
slope([0, 0], [1, 1]) // 1
// or as a single line argument
slope([[0, 0], [1, 1]]) // 1
stringify
A type-safe wrapper around JSON.stringify
. This utility is complimented by parse
, Json
, and UnwrapJson
import { parse, stringify } from '@bedard/utils'
const json = stringify({ foo: 'bar' })
const obj = parse(json) // { foo: string }
stringifyColor
Convert [red, green, blue, alpha?]
values to string using hexadecimal notation.
import { stringifyColor } from '@bedard/utils'
stringifyColor([255, 0, 0]) // #ff0000
toKeyedObjects
Create keyed objects from an array.
import { toKeyedObjects } from '@bedard/utils'
toKeyedObjects([1, 2], 'foo') // [{ foo: 1 }, { foo: 2 }]
Types
AllEqual<Sources, Value>
BreakWords<T>
Byte
CamelCase<T>
CamelCaseKeys<T>
CamelCaseKeysDeep<T>
Difference<A, B>
Equal<A, B>
Expect<T>
First<T>
Hex
HexColor<T>
Intersection<A, B>
Join<Parts, Delimeter>
Json<T>
KebabCase<T>
KebabCaseKeys<T>
KebabCaseKeysDeep<T>
Last<T>
Line<T>
MapCapitalize<T>
MapLowercase<T>
MapUppercase<T>
Methods<T>
Not<T>
OmitStartsWith<T, U>
OmitType<T, U>
Opaque<T, Token>
OptionalKeys<T, U>
PascalCase<T>
PascalCaseKeys<T>
PascalCaseKeysDeep<T>
PickStartsWith<T, U>
PickType<T, U>
Pop<T>
Properties<T>
RequiredKeys<T, U>
RgbColor<T>
ScreamingSnakeCase<T>
ScreamingSnakeCaseKeys<T>
ScreamingSnakeCaseKeysDeep<T>
Shift<T>
SnakeCase<T>
SnakeCaseKeys<T>
SnakeCaseKeysDeep<T>
Split<Source, Delimeter>
StartsWith<T, U>
SymmetricDifference<A, B>
Transparent<T>
Trim<T>
UnwrapJson<T>
UnwrapOpaque<T>
ValueOf<T>
Vector<T>
Without<A, B>
XOR<A, B>
AllEqual<Sources, Value>
Types true
if all Sources
equal Value
.
import { AllEqual } from '@bedard/utils'
type Good = AllEqual<[1, 1], 1> // true
type Bad = AllEqual<[1, 2], 1> // false
BreakWords<T>
Explode a string by common word breaks. This currently includes spaces, hyphens, underscores, and casing changes.
import { BreakWords } from '@bedard/utils'
type Words = BreakWords<'one twoThree-four'> // ['one', 'two', 'Three', 'four']
Byte
A union of all numbers that can be represented by a single byte (0 - 255).
import { Byte } from '@bedard/utils'
const n: Byte = 255
CamelCase<T>
Convert a string to camel case.
import { CamelCase } from '@bedard/utils'
type Str = CamelCase<'foo-bar'> // 'fooBar'
CamelCaseKeys<T>
Camel case object keys.
import { CamelCaseKeys } from '@bedard/utils'
type Obj = CamelCaseKeys<{ foo_bar: any }> // { fooBar: any }
CamelCaseKeysDeep<T>
Deeply camel case object keys.
import { CamelCaseKeysDeep } from '@bedard/utils'
type Obj = CamelCaseKeysDeep<{ foo_bar: { one_two: any }}> // { fooBar: { oneTwo: any }}
Difference<A, B>
Elements of A
that are not elements of B
. For unions, this is the same as the Exclude
utility.
import { Difference } from '@bedard/utils'
type Left = Difference<{ a: any, b: any }, { b: any, c: any }> // { a: any }
Equal<A, B>
Types true
if A
and B
are equal. This is mainly used with Expect
to verify that types are working as expected. See NotEqual
for the inverse of this type.
import { Expect, Equal } from '@bedard/utils'
type Test = Expect<Equal<number, number>>
Expect<T>
Verify that T
is true
. This allows for assertions to be made using the type system. See Equal
and NotEqual
for more usage examples.
import { Expect } from '@bedard/utils'
type Test = Expect<true>
First<T>
Extract the first element of a string or array.
import { First } from '@bedard/utils'
type FirstChar = First<'abc'> // 'a'
type FirstItem = First<[1, 2, 3]>, // 1
Hex
A hexadecimal character
import { Hex } from '@bedard/utils'
const char: Hex = 'a'
HexColor<T>
Validate a hexadecimal color value
import { HexColor } from '@bedard/utils'
const color = <T>(val: HexColor<T>) => val
color('#abc')
Intersection<A, B>
The intersection of A
and B
, giving preference to A
.
import { Intersection } from '@bedard/utils'
type Shared = Intersection<{ a: any, b: number }, { c: string, d: any }> // { b: number }
Join<Parts, Delimeter>
Join Parts
by Delimeter
. This type is the opposite of Split
.
import { Join } from '@bedard/utils'
type Str = Join<['a', 'b', 'c']> // 'abc'
type Parts = Join<['a', 'b', 'c'], '.'> // 'a.b.c'
Json<T>
Encodes a JSON string with underlying type information. This utility is complimented by parse
, stringify
, and UnwrapJson
.
import { Json } from '@bedard/utils'
type UserJson = Json<{ foo: 'bar' }> // string
KebabCase<T>
Convert a string to kebab case.
import { KebabCase } from '@bedard/utils'
type Str = KebabCase<'fooBar'> // 'foo-bar'
KebabCaseKeys<T>
Kebab case object keys.
import { KebabCaseKeys } from '@bedard/utils'
type Obj = KebabCaseKeys<{ foo_bar: any }> // { 'foo-bar': any }
KebabCaseKeysDeep<T>
Deeply kebab case object keys.
import { KebabCaseKeysDeep } from '@bedard/utils'
type Obj = KebabCaseKeysDeep<{ foo_bar: { one_two: any }}> // { 'foo-bar': { 'one-two': any }}
Last<T>
Extract the last element of a string or array.
import { Last } from '@bedard/utils'
type LastChar = Last<'abc'> // 'c'
type LastItem = Last<[1, 2, 3]>, // 3
Line<T>
Describes a straight line between two vectors of length T
.
import { Line } from '@bedard/utils'
type Line2D = Line<2> // [[number, number], [number, number]]
MapCapitalize<T>
Capitalize the first letter of each string.
import { MapCapitalize } from '@bedard/utils'
type Capitalized = MapLowercase<['foo', 'bar']> // ['Foo', 'Bar']
MapLowercase<T>
Map strings to lowercase.
import { MapLowercase } from '@bedard/utils'
type Lower = MapLowercase<['A', 'B']> // ['a', 'b']
MapUppercase<T>
Map strings to uppercase.
import { MapUppercase } from '@bedard/utils'
type Upper = MapUppercase<['a', 'b']> // ['A', 'B']
Methods<T>
Create a string union of methods from T
. This is the inverse of Properties<T>
import { Methods } from '@bedard/utils'
type Foo = Methods<{ foo: string, bar(): any }> // 'bar'
Not<T>
Reverse the boolean value of T
.
import { Not } from '@bedard/utils'
type Test = Not<true> // false
OmitStartsWith<T, U>
Omit keys of T
that start with U
.
import { OmitStartsWith } from '@bedard/utils'
type Foo = OmitStartsWith<{ FooOne: void; FooTwo: void; BarThree: void }, 'Bar'> // { FooOne: void; FooTwo: void }
OmitType<T, U>
Omit keys of T
that extend U
. This is the inverse of PickType<T, U>
.
import { OmitType } from '@bedard/utils'
type Foo = OmitType<{ foo: string, bar: number }, string> // { bar: number }
Opaque<T, Token>
Opaque type T
with an optional Token
. For more on opaque types, this article is a great place to start.
import { Opaque } from '@bedard/utils'
type USD = Opaque<number, 'usd'>
const dollars = 5 as USD
OptionalKeys<T, U>
Get optional keys from T
, or make keys U
of T
optional.
import { OptionalKeys } from '@bedard/utils'
type Keys = OptionalKeys<{ foo?: any, bar: any }> // 'foo'
type Obj = OptionalKeys<{ foo: any, bar: any }, 'foo'> // { foo?: any, bar: any }
PascalCase<T>
Convert a string to pascal case.
import { PascalCase } from '@bedard/utils'
type Str = PascalCase<'foo-bar'> // 'FooBar'
PascalCaseKeys<T>
Kebab case object keys.
import { PascalCaseKeys } from '@bedard/utils'
type Obj = PascalCaseKeys<{ foo_bar: any }> // { 'foo-bar': any }
PascalCaseKeysDeep<T>
Deeply pascal case object keys.
import { PascalCaseKeysDeep } from '@bedard/utils'
type Obj = PascalCaseKeysDeep<{ foo_bar: { one_two: any }}> // { FooBar: { OneTwo: any }}
PickStartsWith<T, U>
Pick keys of T
that start with U
.
import { PickStartsWith } from '@bedard/utils'
type Obj = PickStartsWith<{ FooOne: void; FooTwo: void ; Bar: void }, 'Foo'> // { FooOne: void; FooTwo: void }
PickType<T, U>
Pick keys of T
that extend U
. This is the inverse of OmitType<T, U>
.
import { PickType } from '@bedard/utils'
type Obj = PickType<{ foo: string, bar: number }, string> // { foo: string }
Pop<T>
Remove the last element of T
.
import { Pop } from '@bedard/utils'
type Items = Pop<['foo', 'bar', 'baz']> // ['foo', 'bar']
Properties<T>
Create a string union of properties from T
. This is the inverse of Methods<T>
.
import { Properties } from '@bedard/utils'
type Foo = Properties<{ foo: string, bar(): any }> // 'foo'
RequiredKeys<T, U>
Get required keys from T
, or make keys U
of T
required.
import { RequiredKeys } from '@bedard/utils'
type Keys = RequiredKeys<{ foo: any, bar?: any }> // 'foo'
type Obj = RequiredKeys<{ foo?: any, bar?: any }, 'foo'> // { foo: any, bar?: any }
RgbColor<T>
Validate a rgb color
import { RgbColor } from '@bedard/utils'
const rgb = <T>(color: RgbColor<T>) => color
rgb('rgb(0, 0, 0)')
ScreamingSnakeCase<T>
Convert a string to screaming snake case.
import { ScreamingSnakeCase } from '@bedard/utils'
type Str = ScreamingSnakeCase<'fooBar'> // 'FOO_BAR'
ScreamingSnakeCaseKeys<T>
Screaming snake case object keys.
import { ScreamingSnakeCaseKeys } from '@bedard/utils'
type Obj = ScreamingSnakeCaseKeys<{ foo_bar: any }> // { FOO_BAR: any }
ScreamingSnakeCaseKeysDeep<T>
Deeply screaming snake case object keys.
import { ScreamingSnakeCaseKeysDeep } from '@bedard/utils'
type Obj = ScreamingSnakeCaseKeysDeep<{ foo_bar: { one_two: any }}> // { FOO_BAR: { ONE_TWO: any }}
Shift<T>
Remove the first element of T
.
import { Shift } from '@bedard/utils'
type Items = Shift<['foo', 'bar', 'baz']> // ['bar', 'baz']
SnakeCase<T>
Convert a string to snake case.
import { SnakeCase } from '@bedard/utils'
type Str = SnakeCase<'fooBar'> // 'foo_bar'
SnakeCaseKeys<T>
Snake case object keys.
import { SnakeCaseKeys } from '@bedard/utils'
type Obj = SnakeCaseKeys<{ fooBar: any }> // { foo_bar: any }
SnakeCaseKeysDeep<T>
Deeply snake case object keys.
import { SnakeCaseKeysDeep } from '@bedard/utils'
type Obj = SnakeCaseKeysDeep<{ fooBar: { oneTwo: any }}> // { foo_bar: { one_two: any }}
Split<Source, Delimeter>
Split Source
by Delimeter
. This type is the opposite of Join
. Note that to split by multiple delimeters the second argument must be a string[]
, as unions will create a distributive conditional type.
import { Split } from '@bedard/utils'
type Characters = Split<'abc'> // ['a', 'b', 'c']
type SingleDelimeter = Split<'a.b.c', '.'> // ['a', 'b', 'c']
type MultipleDelimeters = Split<'a.b-c', ['.', '-']> // ['a', 'b', 'c']
StartsWith<T, U>
Types true
if T
starts with U
.
import { StartsWith } from '@bedard/utils'
type Foo = StartsWith<'FooBar', 'Foo'> // true
SymmetricDifference<A, B>
The symmetric difference of A
and B
.
import { SymmetricDifference } from '@bedard/utils'
type OuterSet = SymmetricDifference<'a' | 'b', 'b' | 'c'> // 'a' | 'c'
type OuterObj= SymmetricDifference<{ a: any, b: any }, { b: any, c: any }> // { a: any, c: any }
Transparent<T>
A type that does not encode any additional data. This is the inverse of Opaque<T>
.
import { Transparent } from '@bedard/utils'
type NonOpaqueString = Transparent<string>
Trim<T>
Trim leading and trailing whitespace
import { Trim } from '@bedard/utils'
type Foo = Trim<' foo bar '> // 'foo bar'
UnwrapOpaque<T>
Unwrap the underlying data of an Opaque<T>
type.
import { UnwrapOpaque } from '@bedard/utils'
type Foo = Opaque<string, 'example'>
type Bar = UnwrapOpaque<Foo> // string
UnwrapJson<T>
Decodes type information from a Json<T>
string.
import { Json, UnwrapJson } from '@bedard/utils'
type UserJson = Json<{ email: string }> // string
type User = UnwrapJson<UserJson> // { email: string }
ValueOf<T>
Generate a union from the values of T
.
import { ValueOf } from '@bedard/utils'
type ArrayValues = ValueOf<Array<string>> // string
type ObjectValues = ValueOf<{ foo: number, bar: string }> // number | string
Vector<T>
Generate a uniform tuple of length T
, with numeric values by default.
import { Vector } from '@bedard/utils'
type Coordinate = Vector<3> // [number, number, number]
type Things = Vector<3, Thing> // [Thing, Thing, Thing]
Without<A, B>
Prohibit properties of A
and omit properties of B
.
import { Without } from '@bedard/utils'
type FooWithoutBar = Without<{ foo: any, bar: any }, { bar: any }> // { foo?: never }
XOR<A, B>
Create an exclusive or between two types. Note that for objects, this differs from a union type in that keys are strictly matched.
import { XOR } from '@bedard/utils'
type FooOrBar = XOR<{ foo: any }, { bar: any }>
const a: FooOrBar = { foo } // pass
const b: FooOrBar = { bar } // pass
const c: FooOrBar = { foo, bar } // fail
Additionally, a tuple can be provided for a chained XOR.
type ValidNumber = XOR<[1, 2, 3]>
const a: ValidNumber = 1 // pass
const b: ValidNumber = 2 // pass
const c: ValidNumber = 3 // pass
const d: ValidNumber = 4 // fail
License
Copyright (c) 2021-present, Scott Bedard
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago