# @bfra\.me/es 中文文档

规范地址：https://npmcn.com/package/%40bfra.me/es/

版本：0\.1\.0
npm 元数据更新时间：2025-12-02T07:02:11.525Z
中文译文更新时间：2026-11-08T00:52:23.184Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40bfra.me/es
原文对照：https://npmcn.com/package/%40bfra.me/es/?lang=original
项目主页：https://github.com/bfra-me/works/tree/main/packages/es#readme
源码仓库：https://github.com/bfra-me/works

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：211 kB，95 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：1 个
- peer 依赖：chokidar ^5\.0\.0
- 首次发布：2025-12-02T07:02:10.615Z
- 最新版本发布：2025-12-02T07:02:10.930Z
- 近 30 天下载量：15484（2026-10-08 至 2026-11-06，npm 官方下载统计）
- 已发布版本数：1（近 12 个月 1 个）

## 中文简介

高质量可再利用类型和公用事业,促进ES发展

## 安装

```sh
npm install @bfra.me/es
```

也可以使用：`pnpm add @bfra.me/es`、`yarn add @bfra.me/es`、`bun add @bfra.me/es`

## README

# @bfra.me/es (英语)

[![npm version](https://img.shields.io/npm/v/@bfra.me/es.svg)](https://www.npmjs.com/package/@bfra.me/es) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

用于ES开发的高质量可再使用类型和公用事业(JavaScript和TypeScript). 核心公用事业的零运行时间依赖性,通过亚路径出口可动摇树木.

## 特征

-   🎯 **结果类型** - 无一例外地对类型安全的错误处理实行歧视性结合
-   🔧 **公用事业** —— 说 `pipe`, (中文(简体) ), `compose`, (中文(简体) ), `curry`, (中文(简体) ), `memoize` 带有完整类型脚本推论
-   📦 **模块接口** ——ES/CommonJS互操作性助手
-   ⏱️ **同步公用事业** —— 说 `retry`, (中文(简体) ), `timeout`, (中文(简体) ), `debounce`, (中文(简体) ), `throttle`,货币控制
-   🏷️ **品牌类型** ——编译时间类型安全,运行时间成本为零
-   ✅ **验证** ——路径验证,输入消毒,常见验证器
-   🔍 **环境检测** ——CI,编辑,git生命周期检测
-   📁 **文件监视器** – 用变化检测器( 可选的 chokidar 端口) 忽略文件监视
-   ⚠️ **错误公用事业** - 有代码、上下文和起因链的结构错误

## 安装

```bash
# pnpm (recommended)
pnpm add @bfra.me/es

# npm
npm install @bfra.me/es

# yarn
yarn add @bfra.me/es
```

### 可选同伴依赖关系

```bash
# For file watcher functionality
pnpm add chokidar
```

## 快速启动

```typescript
import {err, isOk, ok, pipe, retry} from '@bfra.me/es'

// Type-safe error handling with Result
function divide(a: number, b: number) {
  return b === 0 ? err(new Error('Division by zero')) : ok(a / b)
}

const result = divide(10, 2)
if (isOk(result)) {
  console.log(result.data) // 5
}

// Functional composition
const transform = pipe(
  (x: number) => x + 1,
  (x: number) => x * 2
)
transform(5) // 12

// Async with retry
const data = await retry(() => fetch('/api/data'), {maxAttempts: 3})
```

## 子路径导出

所有公用设施都组成了可树动的亚道出口。 只导入您需要的 :

| 导出 | 说明 |
| --- | --- |
| `@bfra.me/es/result` | 处理错误的结果类型 |
| `@bfra.me/es/functional` | 职能方案拟订公用事业 |
| `@bfra.me/es/async` | Async 公用设施(重复、超时、停用) |
| `@bfra.me/es/module` | ES模块互通性 |
| `@bfra.me/es/types` | 品牌类型和类型警卫 |
| `@bfra.me/es/validation` | 路径验证和消毒 |
| `@bfra.me/es/error` | 结构错误公用设施 |
| `@bfra.me/es/env` | 环境检测 |
| `@bfra.me/es/watcher` | 文件监视器抽象 |

## API 参考

### 结果类型( E)`@bfra.me/es/result`(中文(简体) )

歧视工会类型,无一例外地处理错误。 受到Rust的启发 `Result` 类型.

```typescript
import type {Err, Ok, Result} from '@bfra.me/es/result'
import {err, flatMap, isErr, isOk, map, ok, unwrap, unwrapOr} from '@bfra.me/es/result'
```

#### 创造结果

```typescript
// Create success result
const success = ok(42)              // Ok<number>

// Create error result
const failure = err(new Error('failed'))  // Err<Error>
```

#### 结果类型守护

```typescript
const result = divide(10, 2)

if (isOk(result)) {
  // TypeScript knows result.data is available
  console.log(result.data)
}

if (isErr(result)) {
  // TypeScript knows result.error is available
  console.error(result.error)
}
```

#### 转变结果

```typescript
// map: Transform success values
const doubled = map(ok(5), x => x * 2)  // Ok(10)
const mapped = map(err('fail'), x => x * 2)  // Err('fail') - unchanged

// flatMap: Chain operations that return Results
const parsed = flatMap(ok('42'), str => {
  const num = Number.parseInt(str, 10)
  return Number.isNaN(num) ? err('Invalid number') : ok(num)
})

// mapErr: Transform error values
const withContext = mapErr(err('not found'), e => new Error(`Resource ${e}`))
```

#### 提取值

```typescript
// unwrap: Get value or throw (use sparingly)
const value = unwrap(ok(42))  // 42
const willThrow = unwrap(err('fail'))  // throws Error

// unwrapOr: Get value or default (preferred)
const withDefault = unwrapOr(err('fail'), 0)  // 0
```

#### 环绕掷出代码

```typescript
import {fromPromise, fromThrowable} from '@bfra.me/es/result'

// Wrap synchronous throwing functions
const parsed = fromThrowable(() => JSON.parse(input))

// Wrap promises
const fetched = await fromPromise(fetch('/api/data'))
```

### 公用事业`@bfra.me/es/functional`(中文(简体) )

```typescript
import {compose, constant, curry, flip, identity, memoize, noop, partial, pipe, tap} from '@bfra.me/es/functional'
```

#### 烟斗

编程函数从左到右。 每个函数都收到前一个函数的结果.

```typescript
const addOne = (x: number) => x + 1
const double = (x: number) => x * 2
const toString = (x: number) => `Value: ${x}`

const transform = pipe(addOne, double, toString)
transform(5)  // "Value: 12" (5 + 1 = 6, 6 * 2 = 12)
```

#### 编曲

由右到左组成函数(数学组成顺序).

```typescript
const addOneThenDouble = compose(double, addOne)
addOneThenDouble(5)  // 12 (addOne first, then double)
```

#### 咖喱

转换函数以接受一个参数.

```typescript
const add = (a: number, b: number, c: number) => a + b + c
const curriedAdd = curry(add)

curriedAdd(1)(2)(3)     // 6
curriedAdd(1, 2)(3)     // 6
curriedAdd(1)(2, 3)     // 6
curriedAdd(1, 2, 3)     // 6
```

#### 记住

Caches 函数结果基于参数. 支持多个缓存策略.

```typescript
import {memoize} from '@bfra.me/es/functional'

// Simple memoization
const expensive = memoize((n: number) => {
  // Complex calculation...
  return n * 2
})

// With LRU cache (evicts least recently used)
const withLRU = memoize(fn, {
  strategy: 'lru',
  maxSize: 100
})

// With TTL (time-to-live expiration)
const withTTL = memoize(fn, {
  strategy: 'ttl',
  ttl: 60000  // 1 minute
})

// Cache statistics
console.log(expensive.getStats())  // { hits: 10, misses: 5, size: 5 }
expensive.clear()  // Clear all cached values
```

#### 其他公用事业

```typescript
// identity: Returns its argument unchanged
const x = identity(42)  // 42

// tap: Execute side effect, return original value
const logged = pipe(
  addOne,
  tap(x => console.log('After addOne:', x)),
  double
)

// partial: Pre-fill some arguments
const greet = (greeting: string, name: string) => `${greeting}, ${name}!`
const sayHello = partial(greet, 'Hello')
sayHello('World')  // "Hello, World!"

// flip: Swap first two arguments
const divide = (a: number, b: number) => a / b
const flipped = flip(divide)
flipped(2, 10)  // 5 (same as divide(10, 2))

// constant: Create function that always returns same value
const alwaysTrue = constant(true)
alwaysTrue()  // true

// noop: Do nothing function
element.addEventListener('click', noop)
```

### 公用事业`@bfra.me/es/async`(中文(简体) )

```typescript
import {debounce, pAll, pLimit, retry, sleep, throttle, timeout} from '@bfra.me/es/async'
```

#### 重试

以指数后退重置函数 .

```typescript
const result = await retry(
  () => fetch('/api/data'),
  {
    maxAttempts: 3,      // Default: 3
    initialDelay: 100,   // Default: 100ms
    maxDelay: 10000,     // Default: 10000ms
    backoffFactor: 2,    // Default: 2
    shouldRetry: (error, attempt) => {
      // Custom retry logic
      return error.message !== 'Not Found'
    }
  }
)

if (isOk(result)) {
  console.log(result.data)
} else {
  console.error('All retries failed:', result.error)
}
```

#### 超时

{\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}我答应你暂停.

```typescript
const result = await timeout(fetch('/api/slow'), 5000)

if (isErr(result) && result.error instanceof TimeoutError) {
  console.log('Request timed out')
}
```

#### 弹跳

创建延迟引用的已跳出函数.

```typescript
const saveInput = debounce((value: string) => {
  localStorage.setItem('draft', value)
}, 300)

input.addEventListener('input', e => saveInput(e.target.value))

// Cancel pending invocation
saveInput.cancel()
```

#### 节流阀

限制函数引用频率 .

```typescript
const handleScroll = throttle(() => {
  updateScrollPosition()
}, 100)

window.addEventListener('scroll', handleScroll)
```

#### 货币控制

```typescript
// pLimit: Create a concurrency limiter
const limit = pLimit(5)  // Max 5 concurrent operations

const results = await Promise.all(
  urls.map(url => limit(() => fetch(url)))
)

// pAll: Run promises with concurrency control
const allResults = await pAll(
  urls.map(url => () => fetch(url)),
  {concurrency: 5}
)
```

### 模块 Interop (`@bfra.me/es/module`(中文(简体) )

```typescript
import {dynamicImport, interopDefault, isESModule, isPackageInScope, resolveModule} from '@bfra.me/es/module'
```

#### 互换默认

解开ES和CommonJS模块的默认导出.

```typescript
// Handles both ESM and CJS exports
const lodash = await interopDefault(import('lodash'))

// Works with dynamic imports
const config = await interopDefault(import('./config.js'))
```

#### 解析器

安全地解决并导入带有结果返回类型的模块.

```typescript
const result = await resolveModule<typeof import('lodash')>('lodash')

if (isOk(result)) {
  const _ = result.data
}
```

#### isPackage InScope 组件

检查是否有来自特定目录上下文的软件包.

```typescript
if (isPackageInScope('typescript', {scopeUrl: import.meta.url})) {
  // TypeScript is available
}
```

### 类型公用事业`@bfra.me/es/types`(中文(简体) )

```typescript
import type {Brand, NonEmptyString, Opaque, PositiveInteger} from '@bfra.me/es/types'
import {assertType, brand, hasProperty, isArray, isNonNullable, isNumber, isObject, isString, unbrand} from '@bfra.me/es/types'
```

#### 品牌类型

在TypeScript的结构类型系统中创建标称类型.

```typescript
type UserId = Brand<string, 'UserId'>
type OrderId = Brand<string, 'OrderId'>

function getUser(id: UserId): User { /* ... */ }
function getOrder(id: OrderId): Order { /* ... */ }

const userId = brand<string, 'UserId'>('user-123')
const orderId = brand<string, 'OrderId'>('order-456')

getUser(userId)   // ✅ OK
getUser(orderId)  // ❌ Type error - can't use OrderId as UserId
```

#### 类型警卫

```typescript
function processValue(value: unknown) {
  if (isString(value)) {
    // value is string
    return value.toUpperCase()
  }

  if (isNumber(value)) {
    // value is number (excludes NaN)
    return value * 2
  }

  if (isObject(value)) {
    // value is Record<string, unknown> (excludes null and arrays)
    return Object.keys(value)
  }

  if (isArray(value)) {
    // value is unknown[]
    return value.length
  }
}

// Check for property existence
if (hasProperty(obj, 'name')) {
  // obj is Record<'name', unknown>
  console.log(obj.name)
}

// Filter nullish values
const values = [1, null, 2, undefined, 3].filter(isNonNullable)  // [1, 2, 3]
```

#### 类型

```typescript
// Assert and narrow type
assertType(value, isString)  // throws if not string
// value is now string

// Use with custom guards
const isUser = (v: unknown): v is User =>
  isObject(v) && hasProperty(v, 'name') && hasProperty(v, 'email')

assertType(data, isUser)
// data is now User
```

### 审定`@bfra.me/es/validation`(中文(简体) )

```typescript
import {createValidator, isWithinBoundary, sanitizeInput, validatePath} from '@bfra.me/es/validation'
```

#### 路径验证

验证路径 防止逆行攻击.

```typescript
const result = validatePath('../etc/passwd')
if (isErr(result)) {
  console.log(result.error.code)  // 'PATH_TRAVERSAL'
}

const valid = validatePath('src/index.ts')
if (isOk(valid)) {
  // valid.data is ValidPath branded type
}

// Check if path is within boundary
if (isWithinBoundary('/app/uploads/file.txt', '/app/uploads')) {
  // Safe to access
}
```

#### 输入保密

```typescript
const userInput = '<script>alert("xss")</script>'
const safe = sanitizeInput(userInput)
// "&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;"

// With options
const cleaned = sanitizeInput(input, {
  escapeHtml: true,      // Default: true
  removeNullBytes: true, // Default: true
  trim: true             // Default: true
})
```

### 水电费( U)`@bfra.me/es/error`(中文(简体) )

```typescript
import {BaseError, createError, formatError, NotFoundError, PermissionError, TimeoutError, ValidationError, withErrorContext} from '@bfra.me/es/error'
```

#### 结构错误

```typescript
// Create custom errors with code and context
const error = createError('User not found', {
  code: 'USER_NOT_FOUND',
  cause: originalError,
  context: {userId: 123}
})

// Use specialized error types
throw new ValidationError('Invalid email format', {
  field: 'email',
  value: 'not-an-email'
})

throw new NotFoundError('Resource not found', {
  resourceType: 'User',
  resourceId: '123'
})
```

#### 格式化出错

```typescript
try {
  riskyOperation()
} catch (error) {
  // Format any error to string with cause chain
  console.log(formatError(error))
}
```

### 环境探测`@bfra.me/es/env`(中文(简体) )

```typescript
import {getEnvironment, isBrowser, isDeno, isInCI, isInEditorEnv, isInGitLifecycle, isNode} from '@bfra.me/es/env'
```

```typescript
if (isInCI()) {
  // Running in CI (GitHub Actions, Jenkins, etc.)
}

if (isInEditorEnv()) {
  // Running in VS Code, JetBrains, Vim, or Neovim
}

if (isInGitLifecycle()) {
  // Running during git hook (commit, push, etc.)
}

// Runtime detection
if (isNode()) { /* Node.js */ }
if (isBrowser()) { /* Browser */ }
if (isDeno()) { /* Deno */ }

// Get comprehensive environment info
const env = getEnvironment()
// { runtime: 'node', isCI: false, isEditor: true, ... }
```

### 文件监视器( E)`@bfra.me/es/watcher`(中文(简体) )

> **说明:** 要求数 `chokidar` 作为同伴的依赖.

```typescript
import {createChangeDetector, createDebouncer, createFileHasher, createFileWatcher} from '@bfra.me/es/watcher'
```

#### 基本文件监视

```typescript
const watcher = createFileWatcher(['src/**/*.ts', 'test/**/*.ts'], {
  debounceMs: 100,
  ignored: ['**/node_modules/**'],
  usePolling: false
})

watcher.on('change', event => {
  console.log('Changes detected:', event.changes)
  // event.changes: Array<{path: string, type: 'add' | 'change' | 'unlink', timestamp: number}>
})

await watcher.start()

// Later: clean up
await watcher.close()
```

#### 用 Hashing 更改检测

```typescript
const hasher = createFileHasher('sha256')
const detector = createChangeDetector()

// Hash file content
const hash = await hasher.hashFile('/path/to/file.ts')

// Detect changes
const {changed, added, removed} = await detector.detectChanges({
  'src/index.ts': 'abc123...',  // Previous hashes
})
```

## 类型脚本配置

这个软件包需要 5.0+ 类型脚本,并且最能用严格的模式工作:

```json
{
  "compilerOptions": {
    "strict": true,
    "exactOptionalPropertyTypes": true,
    "moduleResolution": "bundler"
  }
}
```

## 套装大小

-   核心公用事业(不包括监视器):小于5KB
-   配备监视器的完整软件包: < 10KB 已修改
-   通过子路径导出支持树摇动

## 所需资源

-   节点.js 20+
-   TypeScript 5.0+ (用于开发)
-   ES2022+ 兼容运行时间

## 相关软件包

-   [`@bfra.me/eslint-config`](https://npmcn.com/package/%40bfra.me/eslint-config) - 使用这些公用事业的ESLint配置
-   [`@bfra.me/tsconfig`](https://npmcn.com/package/%40bfra.me/tsconfig) - 类型脚本配置

## 许可证

麻省理工学院 [马库斯·布朗](https://github.com/marcusrbrown)

## 常见问题

### @bfra\.me/es 是什么？

高质量可再利用类型和公用事业,促进ES发展

### 如何安装 @bfra\.me/es？

在项目目录运行 npm install @bfra\.me/es，或使用 pnpm add / yarn add / bun add。

### @bfra\.me/es 支持 TypeScript 吗？

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

### @bfra\.me/es 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @bfra\.me/es 可以商用吗？

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

### @bfra\.me/es 的下载量有多少？

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

### @bfra\.me/es 还在维护吗？

最新版本 0\.1\.0 发布于 2025/12/02（11 个月前）；至今共发布 1 个版本，其中过去 12 个月发布了 1 个；首次发布于 2025/12/02。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

