【问题标题】:Why is typescript insisting on a type that is implied?为什么打字稿坚持使用隐含的类型?
【发布时间】:2021-03-17 08:49:23
【问题描述】:

@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);
      }, [])

此函数的目的是从其父 Course 对象中获取目标对象数组,并将它们覆盖到目标对象数组中。 基本上把[{[{}]}]转为[{}]

仅供参考,这是父对象数组的一个峰值:

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 会抱怨,对象中当然没有键,为什么显然应该有。

Playground

【问题讨论】:

  • 附带说明:updatedGoals.concat(goal); 不会做任何事情。它结合了两个数组,但它只返回一个新数组。但是,该数组从未使用过,因此被丢弃了。
  • 之前,我只有 ´´´return updatedGoals;´´´ 但这导致最终的目标数组只有最后一个父对象(课程)的目标。
  • 在尝试重新创建它时,我还在 for 循环中尝试了 updatedGoals = updatedGoals.concat(goal); ......但这只会导致最终目标数组具有最后一门课程的目标两次。我很想知道为什么。

标签: typescript type-inference


【解决方案1】:

TypeScript 正在从您的 COURSE_DATA 对象推断类型。由于它是明确定义的,因此它假定这也是对象的确切类型结构。如果您希望它更灵活,请使用接口来声明额外的字段。

如果你想访问 titlecourse 字段,无论如何都应该在某个地方定义它的类型,这就是 TypeScript 的全部思想。否则你只是在类型系统中进进出出,如果你仔细想想,这没有多大意义。

【讨论】:

  • 嗯,我想我会在需要的地方使用它。我想具体说明类型或防止将来出现错误。无论如何,COURSE_DATA 只是虚拟数据。
  • 关于隐式/显式。不是 const car = "BMW" 隐式和 const car: string = "BMW" 显式的吗?那么为什么 COURSE_DATA 或者更准确地说是 COURSE_DATA 中的一个对象是显式的?
  • 没有真正的区别。打字稿将推断字符串类型。它是隐含的,是的,但对于 TypeScript 来说是一样的。如果您只想在应用程序的某些地方使用类型系统,则最好使用流类型系统。
  • 但是你可以有一些 .tsx 文件,不是吗?我使用了一些离子成分。我想用我添加的新功能越来越多地实现 ts。您是否考虑过具体的缺点?
【解决方案2】:

此更新后的代码不再需要@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);
  }, [])

【讨论】:

  • 请不要使用后续问题的答案 - 您可以提出新问题。如果您为其他读者添加解释也会很好
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 2016-11-06
  • 1970-01-01
  • 2021-07-06
  • 1970-01-01
  • 2018-05-24
相关资源
最近更新 更多