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

Javascript Typescript,声明具有不同类型的嵌套对象的最佳方法是什么?,javascript,typescript,typescript-typings,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 :

我有这个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"
          }
        }
      }
    }];

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

我不知道这是不是最好的方法,但我会给你举个例子说明我的方法

我将尝试解释我的一般规则,不仅仅是针对嵌套对象:

对于所有基本类型字符串、数字、布尔值或某个数组的属性,您可以将它们保留为这样,但对于从现在起我将调用“复杂属性”的所有其他复杂属性/嵌套对象,因为对我来说更合理的是,您创建了一个将成为属性类型的接口

示例:在您的示例中,val属性是一个“复杂”属性,所以让我们从下到上拆分它

val属性中最小的复杂属性是target,因此您可以创建一个名为target或ItTarget的接口。在ts target中这样做并不完全是一种约定,它类似于:

interface Target {
  raw: number,
  display: string
}
interface Val {
  today: Day,
  yesterday: Day
}
对已实现的“复杂”属性执行相同的操作

现在你可以上一层楼了。今天,属性也是一个“复杂”的属性,所以它必须有一个可能是某种接口类型的类型。由于我们之前的工作,该界面将如下所示:

interface Day {
  target: Target,
  achieved: Achieved
}
您可能想知道为什么接口被称为Day而不是Today,原因是您必须找出昨天“复杂”属性的类型。正如您所看到的,您可以看到它与today属性的类型相同,因为它内部具有相同的属性

最后,我们的目标val属性将有自己的接口,类似于:

interface Target {
  raw: number,
  display: string
}
interface Val {
  today: Day,
  yesterday: Day
}
接下来,对其他所有“复杂”属性执行相同的操作

现在,您可以在主对象中使用这些对象,它可能是一个类,其属性类型将是这些接口

不要忘记tsand中的接口不仅仅是一个“帮助”工具,它只帮助组织代码设计。大多数情况下,每个接口都必须有一个实现该接口的类。这些类将用于为这些属性设置一些值

4年后更新:


现在,当我有更多的typescript经验时,我仍然会使用相同的策略,但我会使用类型而不是接口来完成几乎相同的工作。我的接口应该只在你想要一个实现它们的类的时候才使用。

我不知道这是不是最好的方法,但我会给你一个这样做的例子

我将尝试解释我的一般规则,不仅仅是针对嵌套对象:

对于所有基本类型字符串、数字、布尔值或某个数组的属性,您可以将它们保留为这样,但对于从现在起我将调用“复杂属性”的所有其他复杂属性/嵌套对象,因为对我来说更合理的是,您创建了一个将成为属性类型的接口

示例:在您的示例中,val属性是一个“复杂”属性,所以让我们从下到上拆分它

val属性中最小的复杂属性是target,因此您可以创建一个名为target或ItTarget的接口。在ts target中这样做并不完全是一种约定,它类似于:

interface Target {
  raw: number,
  display: string
}
interface Val {
  today: Day,
  yesterday: Day
}
对已实现的“复杂”属性执行相同的操作

现在你可以上一层楼了。今天,属性也是一个“复杂”的属性,所以它必须有一个可能是某种接口类型的类型。由于我们之前的工作,该界面将如下所示:

interface Day {
  target: Target,
  achieved: Achieved
}
您可能想知道为什么接口被称为Day而不是Today,原因是您必须找出昨天“复杂”属性的类型。正如您所看到的,您可以看到它与today属性的类型相同,因为它内部具有相同的属性

最后,我们的目标val属性将有自己的接口,类似于:

interface Target {
  raw: number,
  display: string
}
interface Val {
  today: Day,
  yesterday: Day
}
接下来,对其他所有“复杂”属性执行相同的操作

现在,您可以在主对象中使用这些对象,它可能是一个类,其属性类型将是这些接口

不要忘记tsand中的接口不仅仅是一个“帮助”工具,它只帮助组织代码设计。大多数情况下,每个接口都必须有一个实现该接口的类。这些类将用于为这些属性设置一些值

4年后更新:


现在,当我有更多的typescript经验时,我仍然会使用相同的策略,但我会使用类型而不是接口来完成几乎相同的工作。只有当您想要有一个类来实现它们时,才应该使用我的接口。

如果您不想将子类型嵌套字段提取为单独的类,因为它们只在该类中使用 ne place,然后按照下面的代码定义类

导出类MyItem{ 风格:弦乐; 颜色:字符串; id:编号; 完成:布尔; 标签:{ 短:字符串, 长:字符串, statstime:字符串 }; //……等等 构造函数项:任意{ ifitem Object.assignthis,item;//将项目字段复制到此字段 } }; //并将您的非类型化项表(如从API读取的)映射到类型化项
让typedItem:MyItem[]=items.mapitem=>new MyItemItemItem 若您不想将子类型嵌套字段提取为单独的类,因为它们只在那个一个位置使用,那个么请按照下面的代码从head中定义类

导出类MyItem{ 风格:弦乐; 颜色:字符串; id:编号; 完成:布尔; 标签:{ 短:字符串, 长:字符串, statstime:字符串 }; //……等等 构造函数项:任意{ ifitem Object.assignthis,item;//将项目字段复制到此字段 } }; //并将您的非类型化项表(如从API读取的)映射到类型化项
让typedItem:MyItem[]=items.mapitem=>new MyItemItemItem;每个类型的接口应该足够好每个类型的接口应该足够好TypeScript中的接口不必有类来实现它们。它们可以仅用于组织代码和严格键入。在您的示例中,通常可以设置一些值,如:var target={raw:5,display:somestring},其中target只是一个接口。然后:var day={target:target}我同意这个修正。即使在这种情况下,我认为您仍然在创建类似于实现该接口的匿名类的东西。TypeScript中的接口不必有实现它们的类。它们可以仅用于组织代码和严格键入。在您的示例中,通常可以设置一些值,如:var target={raw:5,display:somestring},其中target只是一个接口。然后:var day={target:target}我同意这个修正。即使在这种情况下,我认为您仍然在创建类似于实现该接口的匿名类的东西。