首页 > 解决方案 > TypeScript:正确处理递归类型

问题描述

编辑

我又进了一步。更复杂的示例如下所示(Playground):

type DeepFunctions = {
  [key: string]: ((...args: any[]) => any) | DeepFunctions
}

function changeDeepFunctions<T extends DeepFunctions>(deepFunctions: T): T {
  const copy = {...deepFunctions} as DeepFunctions;

  for(let key in copy) {
    const value = deepFunctions[key];
    if(value instanceof Function) {
      copy[key] = ((...args) => {
        console.log("hi");
        return value(...args);
      });
    } else {
      copy[key] = changeDeepFunctions(value);
    }
  }

  return copy as T;
}

一切都很好,输出与应有的完全一样。但是,我不明白为什么我需要这样做。也许还有人可以帮助我理解。

原帖

我对打字稿有点陌生,对于一个看似简单的问题,我找不到一个好的解决方案。

您在此处看到的所有代码都记录在此PlayGround中。

因为我的真实示例有点太重了,所以我将其简化为这些(希望:))相同的示例:

  1. 我想编写一个函数来获取具有多个函数的对象并将其映射到具有映射函数的对象。有点难以描述,但用代码很容易理解:
type Functions = {
  [key: string]: (...args: any[]) => any;
};

export function changeFunctions<T extends Functions>(functions: T): T {
  const copy = { ...functions };

  for (let key in functions) {
    const func = functions[key];
    copy[key] = ((...args) => {
      console.log("hi");
      return func(...args);
    });
  }

  return copy;
}

如果您查看了操场中的代码,您可以看到

copy[key] = ...

行产生类型错误:Type '(...args: any[]) => any' is not assignable to type 'T[Extract<keyof T, string>]'.(2322) 可以通过添加为 typeof func来修复在作业结束时,但感觉不对。

有没有一种干净的方法来写这个?

第二个示例扩展了第一个示例,因此解决方案可能类似:

  1. 作为 1. 的扩展,该函数现在应该能够正确转换包含函数的对象,但也可以递归地包含其他具有函数的对象。这是代码:
type DeepFunctions = {
  [key: string]: ((...args: any[]) => any) | DeepFunctions
}

function changeDeepFunctions<T extends DeepFunctions>(deepFunctions: T): T {
  const copy = {...deepFunctions};

  for(let key in deepFunctions) {
    const value = deepFunctions[key];
    if(value instanceof Function) {
      copy[key] = ((...args) => {
        console.log("hi");
        return value(...args);
      });
    } else {
      // it must be a DeepFunctions object
      copy[key] = changeDeepFunctions(value);
    }
  }

  return copy;
}

正如您在操场上看到的那样,copy[key]分配失败的方式与上面的示例相同。另一个任务:

copy[key] = changeDeepFunctions(value);

不会引发错误。但是,类型仍然是错误的。将鼠标悬停在value上会显示never类型。

您是否有任何提示如何以正确的类型在打字稿中正确编写此类方法?

标签: typescript

解决方案


推荐阅读