![](/img/trans.png)
[英]What is the best approach to work with nested object in this.state?
[英]Typescript , what's the best approach for declaring a nested object with different types?
我有这个 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 的接口(或 ITarget 在 ts 中并不完全是这样做的约定)Target 将类似于:
interface Target {
raw: number,
display: string
}
您对achieved
“复杂”属性执行相同的操作。
现在您可以上一级。 Today
属性也是一个“复杂”的属性,所以它必须有一种类型,可能是某种类型的接口。 由于我们之前的工作,界面看起来像:
interface Day {
target: Target,
achieved: Achieved
}
您可能想知道为什么接口被称为 Day 而不是 Today,原因是您必须找出yesterday
“复杂”属性的类型。 如您所见,您可以看到它与today
属性的类型相同,因为它内部具有相同的属性。
因此,最终作为我们目标的val
属性将拥有自己的接口,类似于:
interface Val {
today: Day,
yesterday: Day
}
接下来,您对所有其他“复杂”属性执行相同的操作。
现在你可以在你的主对象中使用它们,它可能是一个类,它的属性类型将是那些接口。
不要忘记 ts 中的界面(不仅是)只是一个“帮助”工具,它仅有助于组织您的代码设计。 大多数时候,每个接口都应该有一个实现该接口的类。 这些是您将用于为这些属性实际设置某些值的类。
更新(4年后):
现在,当我对打字稿有更多经验时,我仍然会使用相同的策略,但我会使用type
而不是interface
来完成几乎相同的工作。 接口(对我来说)应该只在你打算有一个实现它们的类时使用。
如果你不想提取子类型(嵌套字段作为单独的类),因为它们只在那个地方使用,那么定义类如下(来自 head 的代码)
export class MyItem { style: string; color: string; id: number; done: boolean; label: { short: string, long: string, statstime: string }; // ... and so on constructor(item: any) { if(item) Object.assign(this, item); // copy item fields to "this" fields } }; // and map your not-typed items table (eg readed from API) to typed let typedItem: MyItem[] = items.map(item => new MyItem(item));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.