Typescript ,声明具有不同类型的嵌套对象的最佳方法是什么?

Phi*_*Dev 2 javascript typescript typescript-typings

我有这个 JS 对象,我想将它移植到 Typescript:

var items = [{
      style: 'activity-8',
      color: '#a32c62',
      id:    8,
      done : false,
      label : {
        short :'999 m',
        long  :'walk 999m',
        statstime  :'yesterday'
      },
      val : {
        today : {
          target   : { 
            raw : 0,
            display :"11"
          },
          achieved : {
            raw : 0,
            display :"22"
          }
        },
        yesterday : {
          target   : {
            raw : 0,
            display :"33"
          },
          achieved : {
            raw : 0,
            display :"44"
          }
        }
      }
    },{
      style: 'activity-7',
      color: '#ec575d',
      id:    7,
      done : true,
      label : {
        short :'walk 555m',
        long  :'walk 555m',
        statstime  :'yesterday'
      },
      val : {
        today : {
          target   : { 
            raw : 0,
            display :"0"
          },
          achieved : {
            raw : 0,
            display :"0"
          }
        },
        yesterday : {
          target   : {
            raw : 0,
            display :"0"
          },
          achieved : {
            raw : 0,
            display :"0"
          }
        }
      }
    }];
Run Code Online (Sandbox Code Playgroud)

声明此对象类型的最佳方法是什么?我应该写下每个字段的类型吗?还是创建自定义类型?还有其他建议吗?

chn*_*ing 8

我不知道这是否是“最佳”方式,但我会举个例子来说明我的做法。

我将尝试解释我的一般规则,不仅适用于嵌套对象:

对于所有基本类型(字符串、数字、布尔值或某些数组)的属性,您可以将它们保留为这样,但对于从现在开始我将称为“复杂属性”的所有其他复杂属性/嵌套对象(因为它对我来说更有意义)你制作了一个接口,它将成为属性的类型。

示例:在您的情况下,该val属性是一个“复杂”属性,因此让我们从下到上拆分它。

val 属性中最小的复杂属性是target,因此您创建了一个名为 Target 的接口(或 ITarget 在 ts 中执行此操作并不是完全约定)Target 将类似于:

interface Target {
  raw: number,
  display: string
}
Run Code Online (Sandbox Code Playgroud)

您对achieved“复杂”属性执行相同的操作。

现在您可以上一级。Today属性也是一个“复杂”的属性,因此它必须具有一种可能是某种类型的接口的类型。由于我们之前的工作,界面看起来像:

interface Day {
  target: Target,
  achieved: Achieved
}
Run Code Online (Sandbox Code Playgroud)

您可能想知道为什么接口被称为 Day 而不是 Today,原因是您必须找出yesterday“complex”属性的类型。如您所见,您可以看到它与today属性的类型相同,因为它内部具有相同的属性。

所以最终val,作为我们目标的属性将拥有自己的界面,类似于:

interface Val {
  today: Day,
  yesterday: Day
}
Run Code Online (Sandbox Code Playgroud)

接下来,您对所有其他“复杂”属性执行相同的操作。

现在你可以在你的主对象中使用它们,它可能是一个类,它的属性类型将是那些接口。

不要忘记 ts 中的界面(不仅是)只是一个“帮助”工具,它仅有助于组织您的代码设计。大多数时候,每个接口都应该有一个实现该接口的类。这些是您将用于为这些属性实际设置某些值的类。

更新(4年后):

现在,当我对打字稿有了更多经验时,我仍然会使用相同的策略,但我会使用typeinterface不做几乎相同的工作。接口(对我来说)应该只在你打算有一个实现它们的类时使用。

  • TypeScript 中的接口不必具有实现它们的类。它们仅可用于组织代码和严格键入。在您的示例中,您通常可以设置一些值,例如:`var target = <Target>{raw: 5, display: "somestring"}`(其中 `Target` 只是接口)。然后:`var day = <Day>{target: target}` (2认同)