当我试图推断一个对象不是空的时,我遇到了一个问题.

GIVEN

我有这个函数getAllListLabels和定制的isEmpty判断函数.

export function getAllListLabels(list: Array<Labels> | undefined) {
  if (isEmpty(list)) {
    return null;
  }
  return list.map((value) => value.label).join(", ");
}
export function isEmpty<T>(obj: T) {
   if (!obj) {
    return true;
   }
  if (Array.isArray(obj)) {
    return isNonEmptyArray(obj);
  }
   return Object.getOwnPropertyNames(obj).length === 0;
 }

Problems 使用这个isEmpty函数,当我try 映射时,我的列表将遵守,因为它可能仍未定义'list' is possibly 'undefined'.ts(18048)

Expected个 我有一个uniq函数,它可以正确地推断我的参数(如果没有定义的话)

Tries 我try 了重载函数,但没有好的结果,我也try 了这个帖子,同样的结果是Typescript - generic type guard for isEmpty function.

答案标记为Resolve并不能解决我的问题,因为我希望将其保留在一个函数中.

我用两个独立的函数来解决我的问题,一个用于数组,一个用于对象,如下所示,但我不想这样.

function isNonEmptyArray<T>(obj: T[] | undefined): obj is T[] {
  return (
    obj !== undefined && obj !== null && Array.isArray(obj) && obj.length > 0
  );
}

function isNonEmptyObject<T>(obj: T | undefined): obj is T {
  return (
    obj !== undefined && obj !== null && Object.getOwnPropertyNames(obj).length !== 0
  );
}

推荐答案

这里有一种可能的方法:

type Falsy = false | 0 | 0n | "" | null | undefined;

function isEmpty(obj: any):
  obj is Falsy | never[] | { [k: string]: never } {
  return !obj || (Array.isArray(obj) && !obj.length) ||
    !Object.getOwnPropertyNames(obj).length;
}

这应该会将输入范围缩小到"空"的范围.

第一个判断!obj对应于输入是否为falsy,它只能用Typescript 表示sort of.正如前面提到的in this comment on ms/TS#9407,TypeScrip没有NaN literal type,所以这个函数在面对NaN时会做一些意想不到的事情.Falsy型只是最大的努力.

否则,我们判断类型为never的空数组,或类型为{ [k: string]: never }的空对象.

我肯定有一些奇怪的边缘情况,但对于您的示例代码来说,这是预期的:

function getAllListLabels(list: Array<Labels> | undefined) {
  if (isEmpty(list)) {
    return null;
  }
  return list.map((value) => value.label).join(", "); // okay
}

Playground link to code

Typescript相关问答推荐

TypScript如何在 struct 上定义基元类型?

从接口创建类型安全的嵌套 struct

APP_INITIALIZER—TypeError:appInits不是函数

SortKey类型不起作用,尽管它使用的单个类型工作正常<>'

数组文字中对象的从键开始枚举

我想创建一个只需要一个未定义属性的打字脚本类型

我可以为情态车使用棱角形的路由守卫吗?

Angular NgModel不更新Typescript

TS2339:类型{}上不存在属性消息

分解对象时出现打字错误

为什么ESLint会抱怨函数调用返回的隐式`any`?

为什么我在这个重载函数中需要`as any`?

在组件卸载时try 使用useEffect清除状态时发生冲突.react +打字

类型与泛型抽象类中的类型不可比较

TS不能自己推断函数返回类型

有没有一种方法可以提升对象的泛型级别,而对象的值是泛型函数?

Typescript:是否将联合类型传递给重载函数?

传入类型参数<;T>;变容函数

如何将 MUI 主题对象的自定义属性与情感样式组件中的自定义props 一起使用?

如何确定剧作家中给定定位器的值?