# Conflicts: # docs/module-graph.i18n.yaml # docs/module-graph.md # docs/module-graph.zh.md # packages/session/session-projection/src/invariant.ts # tsconfig.base.json |
||
|---|---|---|
| .. | ||
| src | ||
| package.json | ||
| README.i18n.yaml | ||
| README.md | ||
| README.zh.md | ||
| tsconfig.json | ||
| description | kind |
|---|---|
| Nominal string types and stateless constructors for packages that own identifiers crossing package boundaries. | package-library |
@deepseek-ai/dsh-brand
English | 中文
Summary
dsh-brand makes structurally identical strings non-interchangeable at the type level: a SessionId cannot be passed where a ToolCallId is expected even though both are plain strings at runtime. brandString<T>() applies a nominal brand to one domain-owned string without shared runtime state and lets capability packages own their concrete id types without importing an unrelated capability.
Table of Contents
Use this package
Brand the ids a package owns when they cross a package boundary and could plausibly be confused with another package's ids; not every string needs a brand. A branded id is a contract for TypeScript callers: it only ever enters the functions that expect it, and an id from another package is rejected at compile time.
Branding a string
Declare the branded type in the owning package and apply it at the point where that package admits a string:
import { brandString, type Branded } from '@deepseek-ai/dsh-brand'
export type SessionId = Branded<'SessionId'>
const sessionId = brandString<SessionId>('session-1')
brandString() changes only the static type and performs no runtime validation. Validate domain grammar before calling it when the owning type has one. Once branded, the id compares, logs, serializes to JSON, and crosses the wire as an ordinary string.
When to brand
Brand ids that cross package boundaries and could plausibly be confused — ToolCallId in dsh-llm, the shared agent/session SessionId in dsh-session, JobId in dsh-jobs, LspProviderId in dsh-lsp. Strings that never leave their owning package do not need this abstraction.
Understand the implementation
Implementation internals — click to expand
The primitive is one intersection type: string & { readonly [BRAND]: B }, where BRAND is a module-private unique symbol.
Source map
| File | Role |
|---|---|
src/index.ts |
Branded string type and its stateless constructor |
| — | No runtime invariant companion is published; this pure utility owns no event stream or mutable runtime data; its value algebra is enforced by unit tests. |
How values stay portable
The private symbol never exists at runtime: TypeScript erases it, so branded values have no tag or prototype. brandString() returns its input unchanged. Separate installed copies therefore produce interchangeable values without sharing a registry or constructor identity.
Why it stays dependency-free
Keeping these helpers in their own package means dsh-jobs can brand JobId without importing an unrelated capability package, while each capability still owns the meaning and validation of its concrete ids.
Further Exploration
Read these pages when you need the ids this primitive brands or the type conventions around it.
- Core subsystem — where the shared
SessionIdbrand and the type rules are documented. - LSP subsystem —
LspProviderId, a branded provider id built on this primitive. - Jobs package — the
JobIdbrand owned by the jobs capability.
Dev Note
Working context for maintainers — click to expand
None.