Skip to content

Commit

Permalink
Add Brand type (#67)
Browse files Browse the repository at this point in the history
Fix #66
  • Loading branch information
airtoxin authored and piotrwitek committed Feb 24, 2019
1 parent 2270530 commit e119f23
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 0 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ Issues can be funded by anyone and the money will be transparently distributed t
* [`DeepRequired<T>`](#deeprequiredt)
* [`DeepNonNullable<T>`](#deepnonnullablet)
* [`DeepPartial<T>`](#deeppartialt)
* [`Brand<T, U>`](#brandt-u)

## Flow's Utility Types

Expand Down Expand Up @@ -620,6 +621,34 @@ type PartialNestedProps = DeepPartial<NestedProps>;

---

### `Brand<T, U>`

Define nominal type of `U` based on type of `T`.

**Usage:**

```ts
import { Brand } from 'utility-types';

type USD = Brand<number, "USD">
type EUR = Brand<number, "EUR">

const tax = 5 as USD;
const usd = 10 as USD;
const eur = 10 as EUR;

function gross(net: USD): USD {
return (net + tax) as USD;
}

gross(usd); // ok
gross(eur); // Type '"EUR"' is not assignable to type '"USD"'.
```

[⇧ back to top](#flows-utility-types)

---

## Flow's Utility Types

### `$Keys<T>`
Expand Down
2 changes: 2 additions & 0 deletions src/__snapshots__/mapped-types.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

exports[`Assign testType<Assign<Props, NewProps>>() 1`] = `"Pick<Pick<Props, \\"name\\" | \\"visible\\"> & Pick<NewProps, \\"age\\"> & Pick<NewProps, \\"other\\">, \\"name\\" | \\"age\\" | \\"visible\\" | \\"other\\">"`;

exports[`Brand testType<Brand<number, 'USD'>>() 1`] = `"Brand<number, \\"USD\\">"`;

exports[`DeepNonNullable testType<
DeepNonNullable<NestedArrayProps>['first']['second'][number]['name']
>() 1`] = `"string"`;
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export {
Unionize,
WritableKeys,
ReadonlyKeys,
Brand,
} from './mapped-types';

// deprecated
Expand Down
7 changes: 7 additions & 0 deletions src/mapped-types.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
DeepPartial,
WritableKeys,
ReadonlyKeys,
Brand,
_DeepNonNullableArray,
_DeepNonNullableObject,
_DeepReadonlyArray,
Expand Down Expand Up @@ -352,3 +353,9 @@ it('ReadonlyKeys', () => {
// @dts-jest:pass:snap
testType<ReadonlyKeys<ReadWriteProps>>();
});

// @dts-jest:group Brand
it('Brand', () => {
// @dts-jest:pass:snap
testType<Brand<number, 'USD'>>();
});
22 changes: 22 additions & 0 deletions src/mapped-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,3 +399,25 @@ export type WritableKeys<T extends object> = {
export type ReadonlyKeys<T extends object> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, never, P>
}[keyof T];

/**
* Brand
* @desc Define nominal type of U based on type of T.
* @example
* type USD = Brand<number, "USD">
* type EUR = Brand<number, "EUR">
*
* const tax = 5 as USD;
* const usd = 10 as USD;
* const eur = 10 as EUR;
*
* function gross(net: USD): USD {
* return (net + tax) as USD;
* }
*
* // Expect: No compile error
* gross(usd);
* // Expect: Compile error (Type '"EUR"' is not assignable to type '"USD"'.)
* gross(eur);
*/
export type Brand<T, U> = T & { __brand: U };

0 comments on commit e119f23

Please sign in to comment.