在 TypeScript 中始终抽象嵌套类型

2023-11-29 22:06:25 浏览数 (1)

在 TypeScript 中,我看到过多次出现这种情况,您有一个复杂的对象,该对象可能具有嵌套对象,例如下面的示例:

代码语言:typescript复制
interface ComplexObject {
  a: string;
  b: number;
  c: boolean;
  nested: {
    a: string;
    b: number;
    c: boolean;
  }
}

const myObj: ComplexObject = {
  a: 'a',
  b: 1,
  c: true,
  nested: {
    a: 'a',
    b: 1,
    c: true,
  },
};

尽管 TypeScript 不会报错,因为这是有效的代码,但随着对象变得越来越大,接口将变得越来越难以阅读。

现在假设我们想要编写一个以该对象作为输入的函数,可能会进行一些插值,并且可能会返回该对象的子对象,例如嵌套属性,您可能会有以下代码:

代码语言:typescript复制
const printObj = (obj: ComplexObject) => {
  // 做一些处理
  return obj.nested;
};

如果您尝试使用 IntelliSense 检查该函数的输出,您将看到如下内容:

代码语言:typescript复制
const printObj: (obj: ComplexObject) => {
    a: string;
    b: number;
    c: boolean;
}

这仍然是正确的,但是如果您开始拥有大量属性,就会变得难以阅读。

处理类似上面的复杂对象的更好方法是将所有嵌套属性抽象为它们自己的接口/类型。

例如,重写上面的方式是将代码拆分为以下接口:

代码语言:typescript复制
interface ComplexObjectNested {
  a: string;
  b: number;
  c: boolean;
}

interface ComplexObject {
  a: string;
  b: number;
  c: boolean;
  nested: ComplexObjectNested
}

这将有助于将类型/接口分割为更合理可理解的模块,而不是拥有一个可能难以阅读的庞大类型/接口。

现在如果您再次使用 IntelliSense 检查相同的函数,您将获得更加易读的输出:

代码语言:typescript复制
const printObj: (obj: ComplexObject) => ComplexObjectNested

您还可以添加一个优点,即您还可以将嵌套接口用于其他目的,例如您想要用它作为另一个函数的参数:

代码语言:typescript复制
const getAFromNested = (nested: ComplexObjectNested) => nested.a;

// IntelliSense 将解释为
const getAFromNested: (nested: ComplexObjectNested) => string

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞