npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

try-flatten

v1.3.2

Published

✈ 类型安全的扁平化的 try-catch,支持同步函数、回调函数和 PromiseLike

Downloads

32

Readme

try-flatten

✈ 类型安全的扁平化的 try-catch,支持同步函数、回调函数和 PromiseLike

code-review dependency-review Codacy Badge Codacy Badge npm version

为什么需要这个

try-catch 块级作用域带来的问题

先看一段代码:

const somePromise = Promise.resolve({ prop: 'value' });

try {
  // 块级作用域内赋值
  // res类型推断为 {prop: string}
  const res = await somePromise;
  // 类型安全地使用 res
  console.log(res.prop); // 'value'
} catch (err) {
  // 此处 err 类型为 unknown
  console.log(err);
}

但有些时候,我们需要将变量的声明提升到块级作用域外,比如:

const somePromise = Promise.resolve({ prop: 'value' });

// 需要先在 try-catch 块级作用域外定义变量,此处还需要先声明类型
// 由于只提升了声明,但没有提升赋值,需要捕捉期望的返回值类型,并联合 undefined
type Result = typeof somePromise extends Promise<infer T> ? T : never;
let res: Result | undefined;

try {
  // 块级作用域内赋值
  res = await somePromise;
  // 块级作用域内类型仍然安全
  console.log(res.prop); // 'value'
} catch (err) {
  // 此处 err 类型为 unknown
  console.log(err);
}

// 其他操作...

// try-catch 块级作用域外使用该变量
// 此处 res 类型包含 undefined,类型使用不安全
console.log(res.prop); // TS18048: 'res' is possibly 'undefined'.
// 所以还要加有值判断
if (res) {
  console.log(res.prop);
}

可以看到,由于块级作用域的特性,导致 res 的类型被”污染“了, 使用 try-flatten 后,你将可以用一种“扁平化”的方式调用 try-catch, 不用为了类型安全写一些冗余代码。

用上 try-flatten

typeScript playground

import { tryFlatten } from 'try-flatten';

const somePromise = Promise.resolve({ prop: 'value' });
const [err, res] = await tryFlatten(somePromise);

// 只需要判断 err 是否存在即可
if (err) {
  // 此处 err 类型为 Error,res 类型为 undefined
  console.log(err instanceof Error); // true
  console.log(res === undefined); // true
} else {
  // 此处 err 类型为 null,res 类型为 Result
  console.log(err === null); // true
  console.log(res.prop); // 'value'
}

下载安装

npm install try-flatten

使用方法

对同步函数的 try-flatten

import { tryFunction, tryFlatten } from 'try-flatten';

// 推荐使用 tryFunction
const [err, res] = tryFunction(() => 1);
// 与 tryFunction 同价
const [err, res] = tryFlatten(() => 1);

// 只需要判断 err 是否存在即可
if (err) {
  // 此处 err 类型为 Error,res 类型为 undefined
  console.log(err instanceof Error);
  console.log(res === undefined);
  return;
}

// 此处 err 类型为 null,res 类型为 number
console.log(err === null);
console.log(res === 1);

对回调函数的 try-flatten

情况 1:没有入参

import { type Callback, tryCallback, tryFlatten } from 'try-flatten';

const cf = (cb: Callback<number>) => {
    cb(null, 1);
};

// 推荐使用 tryCallback
const [err, res] = await tryCallback(cf);
// 与 tryCallback 等价
const [err, res] = await tryFlatten(cf);

// 只需要判断 err 是否存在即可
if (err) {
  // 此处 err 类型为 Error,res 类型为 undefined
  console.log(err instanceof Error);
  console.log(res === undefined);
  return;
}

// 此处 err 类型为 null,res 类型为 number
console.log(err === null);
console.log(res === 1);

情况 2:有其他入参

import { type Callback, callbackCurry, tryCallback, tryFlatten } from 'try-flatten';

const cf = (a: number, b: number, cb: Callback<number>) => {
  cb(null, a + b + 1);
};

// 推荐使用 tryCallback,不需要额外的 callbackCurry 辅助
const [err, res] = await tryCallback(cf, 1, 2);
// 与 tryCallback 等价
const [err, res] = await tryFlatten(callbackCurry(cf, 1, 2));

// 只需要判断 err 是否存在即可
if (err) {
  // 此处 err 类型为 Error,res 类型为 undefined
  console.log(err instanceof Error);
  console.log(res === undefined);
  return;
}

// 此处 err 类型为 null,res 类型为 number
console.log(err === null);
console.log(res === 4);

对 PromiseLike 的 try-flatten

import { tryPromise, tryFlatten } from 'try-flatten';

// 推荐使用 tryPromise
const [err, res] = await tryPromise(Promise.resolve(1));
// 与 tryPromise 等价
const [err, res] = await tryFlatten(Promise.resolve(1));

// 只需要判断 err 是否存在即可
if (err) {
  // 此处 err 类型为 Error,res 类型为 undefined
  console.log(err instanceof Error);
  console.log(res === undefined);
  return;
}

// 此处 err 类型为 null,res 类型为 number
console.log(err === null);
console.log(res === 1);

启发