https://github.com/hasparus/nom-ts
🤓 TypeScript nominal-typing helpers
https://github.com/hasparus/nom-ts
Last synced: 5 months ago
JSON representation
🤓 TypeScript nominal-typing helpers
- Host: GitHub
- URL: https://github.com/hasparus/nom-ts
- Owner: hasparus
- License: mit
- Created: 2019-07-19T18:22:51.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-01-07T14:51:34.000Z (about 3 years ago)
- Last Synced: 2025-07-04T09:06:58.060Z (6 months ago)
- Language: TypeScript
- Size: 244 KB
- Stars: 11
- Watchers: 1
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-list - nom-ts - typing helpers | hasparus | 9 | (TypeScript)
README
# nom-ts
TypeScript helpers for nominal typing
---
# Problem
- 😀 Nominal types are [pretty useful](https://github.com/Microsoft/TypeScript/blob/69abe49930761aea92dc564f9b6a5db74d6e1be9/src/compiler/types.ts#L1183-L1192).
- 😞 TypeScript doesn't support nominal types ([yet?](https://github.com/microsoft/TypeScript/wiki/Roadmap/69ede9ef95de7bf8764a2f2fa3c3d4c441cc828d#future)).
Great! This is easy to fix right?
The simple trick below solves the problem.
```ts
declare const __brand: unique symbol;
declare const __type: unique symbol;
interface __Brand {
[__brand]: S;
[__type]: T;
}
export type Brand = T & __Brand;
```
But then we encounter some more happy little problems.
```ts
type PlayerId = Brand;
type PlayerScores = Record;
const myId = 1337 as PlayerId;
const scores: PlayerScores = { [myId]: 9001 };
// Element implicitly has an 'any' type because expression
// of type 'Brand' can't be used to
// index type 'Record, number>'.
// ts(7053)
const myScore = scores[myId];
```
**nom-ts aims to address these problems.**
# Goals
- 🦅 no dependencies
- 🦥 all branded types in nom-ts are assignable to their underlying type
without any additional syntax
# The rest of the code
```ts
interface __Flavor {
[__brand]?: S;
/**
* Intersection is distributive over union, but we don't want to "lose" information about T.
* `__type?: T` will be useful for Unbrand.
*/
[__type]?: T;
}
export type Flavor = T & __Flavor;
export type Unbrand = T extends Flavor ? X : T;
export const Unbrand = (x: T) => x as Unbrand;
export type Dict = Record, V>;
```
# Links
- https://github.com/Microsoft/TypeScript/issues/202
- https://basarat.gitbooks.io/typescript/docs/tips/nominalTyping.html
- "Brand" name is taken from
https://michalzalecki.com/nominal-typing-in-typescript/
- "Flavor" name is taken from
https://spin.atomicobject.com/2018/01/15/typescript-flexible-nominal-typing/
- https://github.com/gcanti/newtype-ts
----
#### Credits
This project was bootstrapped with [TSDX](https://github.com/jaredpalmer/tsdx).