在Typescript中将所有null示例转换为undefined的通用方法

qjp7pelc  于 2023-02-25  发布在  TypeScript
关注(0)|答案(7)|浏览(194)

我想写一个函数,把任何对象的属性的所有示例都转换成未定义的。我的许多对象都有嵌套的对象作为属性或值/对象的数组。
在处理这个问题时,我的第一个想法是使用泛型来尝试捕获每个具有泛型类型的属性的类型,然后根据需要将该属性的值从null转换为undefined。
我希望写一个足够通用的函数,可以在我的代码库中的任何不同类型和大小的对象上工作。
我还没能找到一个简单的方法来拥有未知数量的泛型类型,所以我的下一个想法是我必须在任何地方使用any类型。有什么方法可以解决这个问题吗?
我也希望得到一些关于方法/算法本身的建议。我的想法是,我可能需要递归地检查每个属性,看看它本身是否是一个具有子属性的对象,我还需要迭代找到的任何可能也具有空值的数组,或者具有也需要递归检查的对象。
我需要解决/回答的问题:
1.我应该使用泛型还是任何?
1.如果我使用泛型,有没有一种方法可以在发现新类型时动态地分配新的泛型类型?

  1. typescript有更简单的方法来递归地解析对象吗?
    我目前的方法是这样的:
    inputObjectKeys.map(key, index) =>
    然后有一个函数将null转换为undefined,忽略非对象类型,如果它是一个对象则递归。
    我假设我想使用广度优先搜索或深度优先搜索(我倾向于广度优先搜索这个特定的任务)。我假设,因为我需要访问每个节点,我可能会更好地与DFS只是因为内存使用。
8wigbo56

8wigbo561#

accepted answer实际上没有回答这个问题,因为它被要求使用通用的方法。
下面是一个类似的例子,它也能正确地转换返回类型:

type RecursivelyReplaceNullWithUndefined<T> = T extends null
  ? undefined
  : T extends Date
  ? T
  : {
      [K in keyof T]: T[K] extends (infer U)[]
        ? RecursivelyReplaceNullWithUndefined<U>[]
        : RecursivelyReplaceNullWithUndefined<T[K]>;
    };

export function nullsToUndefined<T>(obj: T): RecursivelyReplaceNullWithUndefined<T> {
  if (obj === null) {
    return undefined as any;
  }

  // object check based on: https://stackoverflow.com/a/51458052/6489012
  if (obj.constructor.name === "Object") {
    for (let key in obj) {
      obj[key] = nullsToUndefined(obj[key]) as any;
    }
  }
  return obj as any;
}

功劳归于这位天才的打字:https://github.com/apollographql/apollo-client/issues/2412#issuecomment-755449680

fgw7neuy

fgw7neuy2#

有点晚了,但我认为格兰特的回答可以简化一点。下面这个怎么样:

function removeNulls(obj: any): any {
    if (obj === null) {
        return undefined;
    }
    if (typeof obj === 'object') {
        for (let key in obj) {
            obj[key] = removeNulls(obj[key]);
        }
    }
    return obj;
}
ibrsph3r

ibrsph3r3#

为了递归地处理所有类型:

function cleanNullToUndefined(obj: any): any {
  if (obj === null) {
      return undefined;

  }
  if (typeof obj !== 'object') {
      return obj;

  }
  if (obj instanceof Array) {
    return obj.map(cleanNullToUndefined);
  }

  return Object.keys(obj).reduce((result, key) => ({
    ...result, 
    [key]: cleanNullToUndefined(obj[key])
  }), {});
}
tkclm6bt

tkclm6bt4#

accepted answer不是类型安全的。
This answer是封闭的,但不处理嵌套数组内的null
这会将嵌套对象数组中的null替换为undefined

type RecursivelyReplaceNullWithUndefined<T> = T extends null
  ? undefined
  : T extends (infer U)[]
  ? RecursivelyReplaceNullWithUndefined<U>[]
  : T extends Record<string, unknown>
  ? { [K in keyof T]: RecursivelyReplaceNullWithUndefined<T[K]> }
  : T;

export function nullsToUndefined<T>(
  obj: T,
): RecursivelyReplaceNullWithUndefined<T> {
  if (obj === null || obj === undefined) {
    return undefined as any;
  }

  if ((obj as any).constructor.name === 'Object' || Array.isArray(obj)) {
    for (const key in obj) {
      obj[key] = nullsToUndefined(obj[key]) as any;
    }
  }
  return obj as any;
}
qoefvg9y

qoefvg9y5#

我的回答并不漂亮,但这就是我要做的:

function recurseObject(obj: any) {

    if (obj === null) {
        return undefined;

    } else if (typeof obj !== 'object') {
        return obj;

    } else {

    if (obj instanceof Array) {
        for (let key of obj) {
            recurseObject(key);
    }

    } else {
            for (let key in obj) {

                if (obj[key] === null) {
                    obj[key] = undefined;

                } else if (typeof obj[key] === 'object') {
                    recurseObject(obj[key]);
                }
            }
        }
    }

    return obj;
}
mdfafbf1

mdfafbf16#

export const nullToUndefined = (obj: object) => {
  if (typeof obj === 'object') {
    for (const [key, val] of Object.entries(obj)) {
      if (val === null) {
        obj[key] = undefined;
      } else {
        nullToUndefined(obj[key]);
      }
    }
  }
};
z31licg0

z31licg07#

可以使用真值类型的值。使用!!运算符将值转换为真值类型的值。

if(!!array[0]) { ... } //If array[0] contains a 'truthy' value, e.g. true, 1, not null, not undefined, etc

相关问题