@asleepace/try

中文文档
0.2.1发布于 2025/04/27MITTypeScriptES Module零依赖近 30 天下载 4.3万

TypeScript utilities for exception handling and errors-as-values.

原始使用文档
文档目录23 节
  1. Installation
  2. Quick Start
  3. Result Type
  4. API
  5. Shorthand
  6. Benefits
  7. Testing
  8. Examples
  9. Making Network Requests
  10. Error Handling in a React Component
  11. Chaining Operations
  12. Overview
  13. Return Values
  14. Error Handling
  15. Properties and Methods
  16. Type Safety
  17. Async Support
  18. Instanceof Support
  19. 0.2.1
  20. 0.2.0
  21. 0.14.0
  22. 0.13.0
  23. License

Try

try-catch-cover

Type-safe error handling primitives for modern JavaScript & TypeScript projects.

Installation

Using npm:

npm install @asleepace/try

Using Yarn:

yarn add @asleepace/try

Using Bun:

bun add @asleepace/try

Quick Start

The goal of this package is to provide concise, type-safe and easy to use tools for handling exceptions.

import { Try } from '@asleepace/try'

const [url, error] = Try.catch(() => new URL(userInput))

if (error) return console.warn(error.message)

const [response, networkError] = await Try.catch(() => fetch(url))
const [jsonData, parsingError] = await Try.catch(() => response!.json())

if (parsingError) return console.warn(parsingError.message)

return jsonData.userName

Result Type

The Try.catch(fn) utility returns a special result type Res which is a class that extends a result tuple. The Res class provides some helpful utilities for handling results:

const result = await Try.catch(() => response.json())

// includes powerful type-guards
if (result.isErr()) return console.warn(result.error.message)

// and convenience methods
const json = result.unwrap()

// supports array destructuring
const [user, error] = await Try.catch(async () => {
  const profileUrl = new URL(json.user!.profile)
  return fetch(profileUrl).then((res) => res.json())
})

if (!error) {
  console.log(`Hello, ${user.name}!`)
} else {
  console.warn(error.message)
}

The can be used in conjunction with the array destructuring syntax, which can help if you are only interested in the value or error.

const result = await Try.catch(() =>
  fetch('https://api.users.com/me')
    .then((res) => res.json())
    .then((usr) => usr as User)
)

console.log(result.value) // User  | undefined
console.log(result.error) // Error | undefined

// automatically narrows the type for you!

if (result.isOk()) {
  const user = result.value // User!
} else {
  const fail = result.error // Error!
}

// in some cases you may just want the value or to throw again:

const user = result.unwrap() // User | never

// or you may want the value or a fallback:

const user = result.unwrapOr(cachedUser) // User

API

Try.catch<T>(fn: () => Promise<T>): Promise<[T, undefined] | [undefined, Error]>

Executes a function and returns a tuple containing either:

  • [value, undefined] if the function executes successfully
  • [undefined, error] if the function throws an error

Works with both synchronous and asynchronous functions, automatically returning a Promise for async operations.

Shorthand

This package also exports a shorthand utility called vet which stands for value / error tuple and provides a more concise way to interact with this api.

// Add more examples of the VET shorthand
import { vet } from '@asleepace/try'

// Simple usage
const [value] = vet(() => JSON.parse(data))

// Only get the error
const [, error] = vet(() => JSON.parse(data))

// With TypeScript generics for better type inference
const [user] = vet<User>(() => getUserFromAPI())

Benefits

  • No Try/Catch Blocks: Clean, readable code without nested try/catch structures
  • Type Safety: Full TypeScript support with proper type inference
  • Consistent Pattern: Uniform error handling for both sync and async code
  • Zero Dependencies: Lightweight and dependency-free
  • Isomorphic: Works in both browser and Node.js environments
  • Powerful Results: Type safe, tested and versatile result class

Testing

This package includes a comprehensive test suite. To run the tests:

# Clone the repository
git clone https://github.com/asleepace/try.git
cd try

# Install dependencies
bun install

# Build project & generate types
bun run build

# Run tests
bun test

Examples

Making Network Requests

// handle synchronous operations which can throw with ease...
const encoded = Try.catch(() => JSON.stringify(userInput))

if (!encoded.ok) return encoded.error

const [response, networkError] = await Try.catch(() =>
  fetch('https://api.com/create', {
    method: 'POST',
    body: encoded.value,
  })
)

if (networkError) return networkError

const [user, jsonError] = await Try.catch(response.json)

if (jsonError) return jsonError

return user

Error Handling in a React Component

import React, { useEffect, useState } from 'react'
import { Try } from '@asleepace/try'

function UserProfile({ userId }) {
  const [user, setUser] = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)

  useEffect(() => {
    async function loadUser() {
      setLoading(true)

      const [userData, fetchError] = await Try.catch(async () => {
        const response = await fetch(`/api/users/${userId}`)
        if (!response.ok) throw new Error(`HTTP error ${response.status}`)
        return response.json()
      })

      setUser(userData)
      setError(fetchError)
      setLoading(false)
    }

    loadUser()
  }, [userId])

  if (loading) return <div>Loading...</div>
  if (error) return <div>Error: {error.message}</div>

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  )
}

Chaining Operations

import { Try } from '@asleepace/try'

async function processData(rawData): object | undefined {
  // Step 1: Parse the data
  const [parsed, parseError] = Try.catch(() => JSON.parse(rawData))
  if (parseError) return console.warn(parseError.message)

  // Step 2: Transform the data
  const [transformed, transformError] = Try.catch(() => {
    return parsed.items.map((item) => ({
      id: item.id,
      name: item.name.toUpperCase(),
      value: item.value * 2,
    }))
  })
  if (transformError) return console.warn(transformError.message)

  // Step 3: Save the data
  const saveResult = await Try.catch(async () => {
    const response = await fetch('/api/save', {
      body: JSON.stringify(transformed),
      method: 'POST',
    })
    return response.json()
  })

  if (saveResult.isErr()) return console.warn(saveResult.error)
  return saveResult.unwrap()
}

Specification

Overview

The Try.catch utility provides a type-safe way to handle errors in both synchronous and asynchronous functions, returning a result tuple that contains either a value or an error, but never both.

Return Values

  • Try.catch always returns either a ResultOk<T> or ResultError type, which extends the tuple types [T, undefined] or [undefined, Error] respectively.
  • The returned object is guaranteed to have exactly two elements, with either index 0 or index 1 being undefined.
  • If the function completes successfully, index 0 will contain the return value and index 1 will be undefined.
  • If the function throws an error, index 0 will be undefined and index 1 will contain the error.

Error Handling

  • If a non-Error value is thrown (such as a string, number, or object), it will be automatically converted to an instance of the built-in Error class.
  • Thrown values that aren't already errors will first be coerced to strings and then used to construct a new Error instance.
  • If the function returns an Error object as its value (not thrown), it will be treated as a successful result with the Error as the value at index 0, not as an error case.

Properties and Methods

The returned result object includes several convenience properties and methods:

  • .value: Returns the value at index 0 (the success value) or undefined if an error occurred.
  • .error: Returns the error at index 1 or undefined if the operation was successful.
  • .ok: A boolean property that is true when .error === undefined and false otherwise.
  • .unwrap(): Returns the value if present, or throws the captured error if no value is present.
  • .unwrapOr(fallback): Returns the value if present, or the provided fallback value if no value is present.
  • .toString(): Returns a string representation of the result, displaying either the successful value or the error message.

Type Safety

  • The returned result type correctly narrows in type-guard contexts:
    • When checking if (result.ok), TypeScript will narrow the type to ResultOk<T>.
    • When checking if (!result.ok), TypeScript will narrow the type to ResultError.
  • In ResultOk<T> contexts, result.value is typed as T and result.error is typed as undefined.
  • In ResultError contexts, result.value is typed as undefined and result.error is typed as Error.

Async Support

  • Try.catch supports both synchronous and asynchronous functions.
  • When passed a function that returns a Promise, Try.catch returns a Promise that resolves to a result tuple.
  • Rejected promises are captured and converted to error results, following the same rules as thrown errors.

Instanceof Support

  • The returned result object is an instance of TryResultClass, enabling instanceof checks.
  • This allows for easier type checking and integration with existing code patterns.

Changelog

0.2.1

  • add Res.ok(value) and Res.err(error) initializers
  • add isOk() and isErr() type guards to result
  • move all code into src/index.ts
  • remove junks files and reduce package size
  • remove internal Try.#handler method
  • simplify Try.catch logic
  • simplify types

0.2.0

  • add vet(fn) shorthand
  • add convenience methods
  • Update Result class
  • Update test suite

0.14.0

  • Update README.md
  • Update Try.catch functionality

0.13.0

  • Initial release

License

MIT

版本与发布记录

@asleepace/try 共发布 7 个版本,首次发布于 2025/04/25;过去 12 个月发布了 0 个版本。

版本发布日期距今
0.2.1latest2025/04/271.5 年前
0.2.02025/04/261.5 年前
0.1.42025/04/251.5 年前
0.1.32025/04/251.5 年前
0.1.22025/04/251.5 年前
0.1.12025/04/251.5 年前

关于 @asleepace/try 的常见问题

@asleepace/try 是什么?

TypeScript utilities for exception handling and errors-as-values.

如何安装 @asleepace/try?

在项目目录运行 npm install @asleepace/try,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:typescript(^5)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@asleepace/try 支持 TypeScript 吗?

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

@asleepace/try 支持 ESM 还是 CommonJS?

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

@asleepace/try 可以商用吗?

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

@asleepace/try 的下载量有多少?

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

@asleepace/try 还在维护吗?

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