@coderspirit/nominal

中文文档
4.1.1发布于 2024/08/12MITTypeScriptESM + CJS构建来源已验证近 30 天下载 4.7万

用于您的工程的强大的名义类型

中文使用文档
文档目录9 节
  1. 安装指令
  2. 节点
  3. 品牌
  4. 火焰
  5. 更快的品牌和口味
  6. 属性
  7. 导言
  8. 疯狂的严格
  9. 高级使用型号( 依赖性类型)

@coderspirit/名义上

NPM version TypeScript License npm downloads Known Vulnerabilities Security Score

Nominal 提供有力的工具包 名义打字 打开 字体 零运行时间高空.

它提供三种名义类型:

  • 品牌: 品牌基本符合传统的名义打字概念. 品牌值只能属于一个 品牌,仅标出变量 接受相同数值 品牌。 。 。 .
  • 火焰 : 火焰 和品牌类似,只有一个区别: 有口味 变量还接受相同无品牌/无习惯值 基准类型。 。 。 . 它们在处理"刚性"代码生成器或其他情况时非常有用 在那里,我们将被迫 写出吨的绘图 只是满足类型 检查器.
  • 属性 : 说出逻辑和 数学属性,但也执行一种弱形式的 依赖类型。 。 。 .

虽然每种类型只能有一个 品牌 或一个 风味我们很容易 组合 品牌 或者说 口味 与 属性。 。 。 .

安装指令

节点

# With NPM
npm install --save-dev @coderspirit/nominal

# Or with PNPM
pnpm add --save-dev @coderspirit/nominal

# Or with Yarn:
yarn add --dev @coderspirit/nominal

[TIP] 请注意, 如果您正在开发一个应用程序, 安装是好的 @coderspirit/nominal 作为发展依赖,但可能有必要 以正常或对等的依赖方式安装,以防您正在开发您的 拥有基于它的图书馆.

品牌

import { WithBrand } from '@coderspirit/nominal'

type Email = WithBrand<string, 'Email'>
type Username = WithBrand<string, 'Username'>

const email: Email = '[email protected]' as Email // Ok
const user: Username = 'admin' as Username // Ok
const text: string = email // OK
const anotherText: string = user // Ok

const eMail: Email = '[email protected]' // Error, as we don't have a cast here
const mail: Email = user // Error, as the brands don't match

咨询

  • 虽然我们在这里表演"静态的铸造",但只有在以下情况下才能这样做:
    • 值为字面( 如示例)
    • 在鉴定、消毒和/或反腐败层面.
  • 一种防止其他开发者“伪造”类型的方法是使用 符号而不是字符串作为属性键或属性值定义时 新的名义类型.

火焰

import { WithFlavor } from '@coderspirit/nominal'

type Email = WithFlavor<string, 'Email'>
type Username = WithFlavor<string, 'Username'>

const email: Email = '[email protected]' as Email // Ok
const user: Username = 'admin' as Username // Ok
const text: string = email // OK
const anotherText: string = user // Ok

const eMail: Email = '[email protected]' // Ok, flavors are more flexible than brands
const mail: Email = user // Error, as the flavors don't match

咨询

  • 虽然我们在这里表演"静态的铸造",但只有在以下情况下才能这样做:
    • 值为字面( 如示例)
    • 在鉴定、消毒和/或反腐败层面.
  • 一种防止其他开发者“伪造”类型的方法是使用 符号而不是字符串作为属性键或属性值定义时 新的名义类型.

更快的品牌和口味

类型 WithBrand 财务报告和审定财务报表 WithFlavor虽然目的很简单, 隐藏一个非常复杂的机器 存在的唯一目的就是维护 与其他更复杂的类型完全兼容,例如 WithProperty。 。 。 .

多数时候我们不需要依赖 如此复杂的机制,因为我们 应用 WithBrandh 财务报告和审定财务报表 WithFlavor 基本类型。 所以,如果我们想尽量减少 我们的汇编类型,我们可以选择一个更简单、更快的执行:

import {
  FastBrand,
  FastFlavor,
  WithBrand,
  WithFlavor
} from '@coderspirit/nominal'

// These two types are 100% equivalent, but the second one takes less time to be
// compiled. Notice that they are 100% equivalent only because they were applied
// to "basic" types (without other associated metadata, like `WithProperty`).
type SlowEmailType = WithBrand<string, 'Email'>
type FastEmailType = FastBrand<string, 'Email'>

// Same for flavors.
type SlowPhoneNumberType = WithFlavor<string, 'PhoneNumber'>
type FastPhoneNumberType = FastFlavor<string, 'PhoneNumber'>

属性

导言

要定义带有属性的新类型,我们可以做到:

import { WithProperty } from '@coderspirit/nominal'
type Even = WithProperty<number, 'Parity', 'Even'>
const myEven: Even = 42 as Even

如果我们想将这些属性用作简单的标记, 我们可以省略属性值, 它会默认 true,虽然它不太灵活:

import { WithProperty } from '@coderspirit/nominal'
type Positive = WithProperty<number, 'Positive'>
const myPositive: Positive = 1 as Positive

有意思,你这混蛋 属性

  • WithProperty 具有添加剂、共通性和一能性.
  • 前一点意味着我们不必担心 我们不会因为这个而出现打字不一致的情况.

WithProperty 两者完全兼容:

  • "经典" & 类型运算符 :
    type PositiveEven = WithProperty<number, 'Parity', 'Even'> & WithProperty<number, 'Positive'>
    
  • 巢穴类型 :
    type PositiveEven = WithProperty<WithProperty<number, 'Positive'>, 'Parity', 'Even'>
    

咨询

  • 虽然我们在这里表演"静态的铸造",但只有在以下情况下才能这样做:
    • 值为字面( 如示例)
    • 在鉴定、消毒和/或反腐败层面.
  • 一种防止其他开发者“伪造”类型的方法是使用 符号而不是字符串作为属性键或属性值定义时 新的名义类型.

疯狂的严格

如果我们愿意,我们甚至可以定义"财产类型",以确保我们不设定 无效值 :

import { PropertyTypeDefinition, WithStrictProperty } from '@coderspirit/nominal'
type Parity = PropertyTypeDefinition<'Parity', 'Even' | 'Odd'>

// == WithProperty<number, 'Parity', 'Even'>
type Even = WithStrictProperty<number, Parity, 'Even'>

// == never
type Wrong = WithStrictProperty<number, Parity, 'Seven'>

高级使用型号( 依赖性类型)

属性可以跨函数边界保存

当我们需要验证许多属性时,这个特性可能非常有用 同样的价值,我们不想失去 这条路上的信息与价值 从一个函数传递到另一个函数.

function throwIfNotEven<T extends number>(v: T): WithProperty<T, 'Parity', 'Even'> {
  if (v % 2 == 1) throw new Error('Not Even!')
  return v as WithProperty<T, 'Even'>
}

function throwIfNotPositive<T extends number>(v: T): WithProperty<T, 'Sign', 'Positive'> {
  if (v <= 0) throw new Error('Not positive!')
  return v as WithProperty<T, 'Positive'>
}

const v1 = 42

// typeof v2 === WithProperty<number, 'Parity', 'Even'>
const v2 = throwIfNotEven(v1)

// typeof v3 extends WithProperty<number, 'Parity', 'Even'>
// typeof v3 extends WithProperty<number, 'Sign', 'Positive'>
const v3 = throwIfNotPositive(v2)

选择要跨越函数界限保存哪些属性

在前一个例子中,我们可以增加许多属性,因为我们只是 对价值做出断言。 当我们改变过去的价值观时,我们必须 注意我们保存的东西.

作为我们在这里所说的话的一个简单例子,我们可以看到增加 1 改为 数字变量会翻转它的等分, 因此在这种情况下,我们不想保持 返回值上的财产.

type Even<N extends number = number> = WithProperty<N, 'Parity', 'Even'>
type Odd<N extends number = number> = WithProperty<N, 'Parity', 'Odd'>

// 1. 'Parity' is overwritten (when available)
// 2. 'Sign' is kept only if it's positive
// 3. We discard all other properties because they might stop being true
type PlusOneResult<N> = KeepProperties<
  N extends Even
    ? KeepPropertyIfValueMatches<Odd<N>, 'Sign', 'Positive'>
    : N extends Odd
    ? KeepPropertyIfValueMatches<Even<N>, 'Sign', 'Positive'>
    : KeepPropertyIfValueMatches<N, 'Sign', 'Positive'>,
  'Sign' | 'Parity'
>

function plusOne<N extends number>(v: N): PlusOneResult<N> {
  return v + 1 as PlusOneResult<N>
}

版本与发布记录

@coderspirit/nominal 共发布 23 个版本,首次发布于 2021/03/29;过去 12 个月发布了 0 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
4.1.1latest2024/08/122 年前
4.1.02024/08/092 年前
4.0.52024/08/092 年前
4.0.42024/08/092 年前
4.0.32024/04/092 年前
4.0.22024/04/082 年前

关于 @coderspirit/nominal 的常见问题

@coderspirit/nominal 是什么?

用于您的工程的强大的名义类型

如何安装 @coderspirit/nominal?

在项目目录运行 npm install @coderspirit/nominal,或使用 pnpm add / yarn add / bun add。

@coderspirit/nominal 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@coderspirit/nominal 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@coderspirit/nominal 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@coderspirit/nominal 可以商用吗?

@coderspirit/nominal 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@coderspirit/nominal 的下载量有多少?

根据 npm 官方下载统计,@coderspirit/nominal 在 2026/10/10 – 2026/11/08 这 30 天内被下载 47,292 次,日均约 1,576 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@coderspirit/nominal 还在维护吗?

最新版本 4.1.1 发布于 2024/08/12(2 年前);至今共发布 23 个版本,其中过去 12 个月发布了 0 个;首次发布于 2021/03/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。