使用复杂的“isEmpty”检查时键入推断

问题描述 投票:0回答:1

我有以下功能,像ramdas isEmpty,但根据我自己的需要量身定制:

/**
 * Checks if a value is empty.
 * It will return true for the following cases:
 * null, undefined, empty string, empty Set, empty Map, an object without properties.
 * @param input Can be any value.
 * @example
 *
 *     isEmpty([1, 2, 3]); //=> false
 *     isEmpty([]); //=> true
 *
 *     isEmpty(''); //=> true
 *
 *     isEmpty(null); //=> true
 *     isEmpty(undefined); //=> true
 *
 *     isEmpty({}); //=> true
 *
 *     isEmpty(new Set([1, 2, 3])); //=> false
 *     isEmpty(new Set()); //=> true
 *
 *     isEmpty(0); //=> false
 *
 *     isEmpty(new Date()); //=> true
 *     isEmpty(Date.now()); //=> false
 */
export const isEmpty = (input: any): boolean => {
  const isMapOrSet = input instanceof Map || input instanceof Set;
  return input === null
    || input === undefined
    || (input instanceof String ? input.length > 0 : false)
    || (isMapOrSet ? input.size === 0 : false)
    || (!isMapOrSet && input instanceof Object ? Object.keys(input).length === 0 : false);
};

使用此函数非常简单,但我对boolean返回类型不满意,因为TypeScript无法推断此函数提供的空检查。

例如,以下代码完全正常,但TypeScript会在someResult[0]调用时抱怨可能为null。

const someResult: [] | null = getStuffFromAPI();
const x = isEmpty(someResult)
? {}
: someResult[0]; // TypeScript will complain about a possible _null_ here.

所以问题是:如何改进函数的签名,以便TypeScript可以正确推断返回类型?

我尝试使用conditional types建模自定义返回类型,但我无法弄清楚如何正确。

为了使我100%清楚我正在搜索的内容,这里有一些伪代码(请注意,TS中不存在HasNoElementsIsEmpty):

type IsEmpty<T> =
  T extends null | undefined ? true :
  T extends Map & HasNoElements ? true :
  T extends Set & HasNoElements ? true :
  T extends String & IsEmpty ? true :
  T extends Object & IsEmpty ? true :
  false;

也许我正在思考这个问题,但我想拓宽一下我的视野。

typescript type-inference
1个回答
0
投票

通过改进TypeScript 3.4中泛型的类型推断已经解决了这个问题。所以在我上面的例子中,我基本上得到了我想要的“免费”的所有正确的类型签名。

© www.soinside.com 2019 - 2024. All rights reserved.