typescript 如何编写一个函数,如果对象不可迭代,则类型保护,否则抛出错误?

xqnpmsa8  于 2022-12-27  发布在  TypeScript
关注(0)|答案(1)|浏览(119)

背景

尴尬的库类型:

declare type Extension = {
    extension: Extension;
} | readonly Extension[];

铅字保护装置

export function isIterable(x: any): x is Iterable<unknown> {
  return Symbol.iterator in x;
}

什么有效

使用类型保护

const extensions:Extension = getExtensions();
if (!isIterable(extensions)) { // Guard
  throw Error('extensions should be iterable');
}
console.log(...extensions); // Works

问题

我正在尝试创建一个 * 类型保护辅助函数 *:

import { isIterable } from '../type-guarded/isIterable';

export const throwIfNotIterable = <T,>(value: T) => {
  if (isIterable(value)) {
    return value;
  }

  throw TypeError(
    `Expected to be iterable, instead got ${value} (${typeof value})`
  );
};

注:推断类型:

const throwIfNotIterable: <T>(value: T, name: string) => T & Iterable<unknown>;

尝试次数

尝试1

console.log(...throwIfNotIterable(extensions));

错误代码:

Type 'unknown' is not assignable to type 'Extension'.

尝试2

throwIfNotIterable(extensions, 'not iterable');
console.log(...extensions);

错误代码:

Type 'Extension | undefined' must have a '[Symbol.iterator]()' method that returns an iterator.

我哪里做错了?

jtw3ybtb

jtw3ybtb1#

可以将throwIfNotIterable设置为Assert函数(也可以将其名称改为assertIsIterable,因为Assert函数通常以assert开头):

export function assertIsIterable<T>(
    value: T | Iterable<unknown>
): asserts value is Iterable<unknown> {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    if (!isIterable(value)) {
        throw TypeError(`Expected to be iterable, instead got ${value} (${typeof value})`);
    }
}

// ...

const extensions: Extension = getExtensions();
assertIsIterable(extensions);
console.log(...extensions); // Works

Playground示例

相关问题