Registry / type-stubs / ts-brand

ts-brand

JSON →
library0.2.0jsnpmunverified

ts-brand is a TypeScript library that enables nominal typing through 'type branding,' a technique that intersects a base type with an object type containing a non-existent property. This allows developers to create distinct types (e.g., `PostId`, `UserId`) from a common primitive (like `number`), preventing accidental assignment bugs at compile time even though they share the same runtime representation. The library is currently at version 0.2.0, indicating it's an early-stage but active project. It ships with TypeScript types inherently, as its functionality is entirely type-system based. A key differentiator is its emphasis on ensuring brand uniqueness, offering methods like using recursive interface types as branding to prevent accidental conflation of brands across different definitions, which is a common pitfall in simpler branding implementations. The project's release cadence appears to be driven by contributions, without a fixed schedule.

npm install ts-brand
INSTALL
IMPORT
SIG · TS-BRAND
T
ts-brand
type-stubsjavascriptv0.2.0
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Brand
import { Brand } from 'ts-brand';
const { Brand } = require('ts-brand');
`ts-brand` exports only types. `require` attempts to load a value, leading to a runtime error or a TypeScript error if strict checks are enabled. This is a type-only import.

This quickstart demonstrates how to define and use branded types for nominal typing, preventing common ID-mismatch bugs at compile time. It shows the `Brand` type in action, including recursive branding for enhanced uniqueness.

import { Brand } from 'ts-brand'; // Define the base API declare function getPost(postId: Post['id']): Promise<Post>; declare function getUser(userId: User['id']): Promise<User>; interface User { id: Brand<number, User>; // Branding 'number' with the User interface for strong uniqueness name: string; } interface Post { id: Brand<number, Post>; // Branding 'number' with the Post interface authorId: User['id']; // Correctly typed authorId as a User's branded ID title: string; body: string; } // A function that correctly retrieves the author of a post function authorOfPost(postId: Post['id']): Promise<User> { return getPost(postId).then(post => getUser(post.authorId)); } // Example of how a type error is caught (uncomment to see error) /* function buggyAuthorOfPost(postId: Post['id']): Promise<User> { // This would correctly fail to compile because post.id is Post['id'] // and getUser expects User['id'], even though both are based on 'number'. return getPost(postId).then(post => getUser(post.id)); } */ // To use branded types, you typically cast a base type value. const postIdValue: number = 123; const userIdValue: number = 456; const myPostId: Post['id'] = postIdValue as Post['id']; const myUserId: User['id'] = userIdValue as User['id']; // This would compile: authorOfPost(myPostId); // This would be a compile-time error: // getUser(myPostId); // Type 'Brand<number, Post>' is not assignable to type 'Brand<number, User>'.
Debug
Known issues
gotchaBranded types in `ts-brand` are a compile-time construct and have no runtime impact. At runtime, a branded type like `Brand<number, 'user'>` will simply be a `number`. Any runtime checks or conversions must be implemented manually.
fix
Do not rely on branded types for runtime type checks. Implement runtime validation or assertion functions separately if needed.
affects: >=0.2.0
gotchaTwo branded types are considered the same if they share the same base type and branding type. Care must be taken to ensure that the `Branding` type parameter is truly unique to avoid unintended type conflation across different parts of a codebase.
fix
Use a unique branding type, such as a string literal specific to the context (e.g., `'UserId'`), or for stronger guarantees, use the recursive branding pattern where the branding type refers to its own interface (e.g., `Brand<number, User>`).
affects: >=0.2.0
gotchaWhen upgrading TypeScript, new strictness checks or changes in type inference might expose previously unflagged issues related to type branding or assertions.
fix
Review TypeScript's release notes for breaking changes and adjust type assertions or branded type definitions as necessary, especially when `strictNullChecks` or other strict compiler options are enabled. Consider using assertion functions to encapsulate type checks.
affects: >=0.2.0
gotchaSince `ts-brand` is at an early version (0.2.0), its API surface might evolve, and future minor or major releases could introduce breaking changes or significant modifications to existing types.
fix
Monitor the project's GitHub repository for updates and review changelogs carefully before upgrading to newer versions. Pin exact versions in your `package.json` to mitigate unexpected changes.
affects: >=0.2.0
Errors
Common errors & fixes
Type 'number' is not assignable to type 'Brand<number, "User">'.
Attempting to assign a raw `number` (or other base type) directly to a branded type without an explicit type assertion.
fix
Use a type assertion (`as Brand<number, 'User'>`) to explicitly tell TypeScript that the value conforms to the branded type after validation, or use a utility function that performs the assertion and returns the branded type. `const myUserId: User['id'] = rawNumber as User['id'];`
Type 'Brand<number, Post>' is not assignable to type 'Brand<number, User>'.
Attempting to assign a value of one branded type to a variable expecting a different branded type, even if their underlying base types are the same.
fix
This is the intended behavior of nominal typing. If you genuinely need to convert between distinct branded types, explicitly 'unbrand' to the base type and then 'rebrand' to the target type, typically with a type assertion and appropriate validation logic. E.g., `const convertedUserId: User['id'] = (postAuthorId as number) as User['id'];`
Cannot find name 'Brand'.
This typically occurs when trying to use `Brand` in a JavaScript file that doesn't import types, or when an incorrect CommonJS `require` syntax is used for a TypeScript type-only module.
fix
Ensure you are using `import { Brand } from 'ts-brand';` within a TypeScript file (`.ts` or `.tsx`). If working in a mixed JavaScript/TypeScript project, remember that types are a compile-time construct and not available at runtime via `require`.
Upgrade
Version history
0.2.0latest on npm
Audit
Dependencies

No dependency data recorded yet.

Agent activity
35 hits · last 30 days
node
32
OpenAI (training)
1
Resources
ts-brand — npm install ts-brand · libregistry