2.1.10 • Published 10 months ago

@prosopo/ts-brand v2.1.10

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
10 months ago

Brand your TypeScript types

See our tutorial for more info on what branding is and why you'd want to use it.

Nominal types example

type A = {
    x: number
    y: boolean
    z: string
}

type B = {
    x: number
    y: boolean
    z: string
}

Type A and B are equal in the eyes of TypeScript.

const fn = (a: A) => {
    console.log('do something with A')
}

const obj: B = {
    x: 1,
    y: true,
    z: 'hello',
}

fn(obj) // absolutely fine, even though fn accepts types of A and obj is of type B!

Let's brand A

type ABranded = Brand<A, 'A'> // {
//     x: number;
//     y: boolean;
//     z: string;
// } & {
//     [brandKey]: "A";
// }
const fn = (a: ABranded) => {
    console.log('do something with A')
}

const obj: B = {
    x: 1,
    y: true,
    z: 'hello',
}

fn(obj) // Now this doesn't work, cannot accept any type other than ABranded!

Now the function only accepts a set type.

Mapped type example

Using ABranded from before, we can do conditional typing.

type IsA<T> = T extends ABranded ? true : false

type x = IsA<ABranded> // true
type y = IsA<B> // false

Obviously this is a simple example, but branding enables conditional typing. This would be impossible using regular types in TypeScript, because type B is seen as equal to type A. Read our blog post for a more detailed explanation.

Classes & Instances

You can brand instances of a class or the class itself (which will produce branded instances).

class Dog {
    constructor(public name: string) {}
}

const DogBranded = brandClass(Dog, 'Dog') // adds the 'Dog' brand, making a new type

const dog = new DogBranded('Spot') // ok, of type DogBranded

Conditional typing can now be done using classes.

Or to brand an instance:

const dogBranded = brand(new Dog(), 'Dog') of type Dog & { [brandKey]: 'Dog' }

Unbranding

Simply do the inverse to get back to the original type.

const DogUnbranded = unbrandClass(DogBranded) // same as the Dog class

const dog = new DogUnbranded('Spot') // ok, of type Dog

Or to unbrand an instance:

const dogUnbranded = unbrand(dog) // of type Dog

Get brand

Given a unknown branded value

const b = getBrand(dog) // b is of type 'Dog'

No brand set:

const b = getBrand(someValue) // b is of type '' - i.e. no brand

Important note

Branding is type only, so only available at compile time! This means using things like getBrand() will give you the brand as a type, not as a runtime variable!

2.1.9

10 months ago

2.1.10

10 months ago

2.1.8

10 months ago

2.1.7

10 months ago

2.1.6

10 months ago

2.1.5

10 months ago

2.1.2

11 months ago

2.1.1

11 months ago

2.1.4

11 months ago

2.1.3

11 months ago

2.1.0

11 months ago

2.0.3

12 months ago

2.0.2

12 months ago

1.0.2

1 year ago

0.3.42

1 year ago

1.0.1

1 year ago

2.0.1

1 year ago

2.0.0

1 year ago

0.3.41

1 year ago

0.3.40

1 year ago

0.3.39

1 year ago

0.3.38

1 year ago