为什么打字稿坚持隐含的类型?
Why is typescript insisting on a type that is implied?
在 @ts-ignore
之后的行中,我将一个新的键值对添加到以前看起来像这样的对象:{id:string, text:string}
如您所见:
Webstorm 告诉我类型应该是 {id:string, text:string}
我想知道,为什么 TypeScript 坚持这样做?
我从未声明对象必须只有这两个值。
代码和背景
const goals = COURSE_DATA.map((course) => {
// @ts-ignore
course.goals.forEach(g => g.course = course.title)
return course.goals;
}).reduce((accGoals, curGoals) => {
let updatedGoals = curGoals;
for (let goal of curGoals){
updatedGoals.concat(goal);
}
return accGoals.concat(updatedGoals);
}, [])
这个函数的目的是从它们的父课程对象中取出目标对象数组,并将它们覆盖到一个目标对象数组中。
基本上把 [{[{}]}] 变成 [{}]
仅供参考,这是父对象数组的一个峰值:
const COURSE_DATA = [
{
id: 'c1', title: 'Ionic + React - The Practical Guide', enrolled: new Date("03/05/2121"), goals: [{
id: "c1g1",
text: "Complete Course"
}, {
id: "c1g2",
text: "Learn Something"
}]
},
]
后来,我决定最终目标数组需要包含每个目标的父课程名称:
// @ts-ignore
course.goals.forEach(g => g.course = course.title)
代码在 @ts-ignore
中做到了这一点,但我想了解为什么 TypeScript 会抱怨,对象中当然没有键,为什么显然应该有。
TypeScript 正在从您的 COURSE_DATA
对象推断类型。因为它是显式定义的,所以它假定这也是您的对象的确切类型结构。如果您希望它更灵活,请使用接口来声明额外的字段。
如果你想访问 title
和 course
字段,你应该在某处定义它的类型,这就是 TypeScript 的全部思想。否则你只是在类型系统中进进出出,如果你仔细想想这没有多大意义。
此更新后的代码不再需要 @tsignore:
const goals = COURSE_DATA.map((course) => {
return course.goals.map((goals) => {
return {...goals, course: course.title}
});
}).reduce((accGoals, curGoals) => {
let updatedGoals = curGoals;
for (let goal of curGoals){
updatedGoals.concat(goal);
}
return accGoals.concat(updatedGoals);
}, [])
在 @ts-ignore
之后的行中,我将一个新的键值对添加到以前看起来像这样的对象:{id:string, text:string}
如您所见:
Webstorm 告诉我类型应该是 {id:string, text:string}
我想知道,为什么 TypeScript 坚持这样做? 我从未声明对象必须只有这两个值。
代码和背景
const goals = COURSE_DATA.map((course) => {
// @ts-ignore
course.goals.forEach(g => g.course = course.title)
return course.goals;
}).reduce((accGoals, curGoals) => {
let updatedGoals = curGoals;
for (let goal of curGoals){
updatedGoals.concat(goal);
}
return accGoals.concat(updatedGoals);
}, [])
这个函数的目的是从它们的父课程对象中取出目标对象数组,并将它们覆盖到一个目标对象数组中。 基本上把 [{[{}]}] 变成 [{}]
仅供参考,这是父对象数组的一个峰值:
const COURSE_DATA = [
{
id: 'c1', title: 'Ionic + React - The Practical Guide', enrolled: new Date("03/05/2121"), goals: [{
id: "c1g1",
text: "Complete Course"
}, {
id: "c1g2",
text: "Learn Something"
}]
},
]
后来,我决定最终目标数组需要包含每个目标的父课程名称:
// @ts-ignore
course.goals.forEach(g => g.course = course.title)
代码在 @ts-ignore
中做到了这一点,但我想了解为什么 TypeScript 会抱怨,对象中当然没有键,为什么显然应该有。
TypeScript 正在从您的 COURSE_DATA
对象推断类型。因为它是显式定义的,所以它假定这也是您的对象的确切类型结构。如果您希望它更灵活,请使用接口来声明额外的字段。
如果你想访问 title
和 course
字段,你应该在某处定义它的类型,这就是 TypeScript 的全部思想。否则你只是在类型系统中进进出出,如果你仔细想想这没有多大意义。
此更新后的代码不再需要 @tsignore:
const goals = COURSE_DATA.map((course) => {
return course.goals.map((goals) => {
return {...goals, course: course.title}
});
}).reduce((accGoals, curGoals) => {
let updatedGoals = curGoals;
for (let goal of curGoals){
updatedGoals.concat(goal);
}
return accGoals.concat(updatedGoals);
}, [])