【问题标题】:How do I work with TypeScript correctly when I need to change a type of a property in an object当我需要更改对象中属性的类型时,如何正确使用 TypeScript
【发布时间】:2021-12-24 09:48:03
【问题描述】:

我有这个类表示从 POST 请求传入的 JSON。

class MilkCarton {
  company: string;
  price: number;
  expiredAt?: string;
  // ...20 more properties
}

在我将它存储到我的mongoDB数据库之前,我想将expiredAt的类型更改为Date,所以我有另一个代表数据库架构的类。

class MilkCartonSchema: {
  company: string;
  price: number;
  expiredAt?: Date;
  // ...20 more properties
}

expiredAt 可以为空,我想创建一个对象,该对象复制MilkCarton 类型的对象,但将其expiredAt 转换为Date

prepareMilkForDb(milk: MilkCarton): MilkCartonSchema {
  const preparedMilk = {
    ...milk,
  }

  if (milk.expiredAt) {
    preparedMilk.expiredAt = new Date(milk.expiredAt)
  }

  return preparedMilk;
}

但是我遇到了一个错误,因为preparedMilk 已经推断出它的类型并且expiredAtstring,如果它是string,从 TypeScript 的角度来看它不能变成Date。但我希望它变成Date,在 TypeScript 中正确执行此操作的方法是什么?

编辑: 我最终选择了:

prepareMilkForDb(milk: MilkCarton): MilkCartonSchema {
  const preparedMilk = {
    ...milk,
    ...(milk.expiredAt && {
      expiredAt: new Date(milk.expiredAt)
    }),
  }

  return preparedMilk;
}

这行得通,但不是我想要的,如果我有另一个示例,其中包含 3 个不同的深层嵌套 ISO string 属性需要转换为 Date(和向后),这样做会很脏解决方法。

【问题讨论】:

  • 类似return { ...milk, expiredAt: new Date(milk.expiredAt) },但请注意字符串是可选的命中日期是必需的 - 你为未定义的输入输入什么日期?
  • @jonrsharpe 我修复了它date 也应该是可选的。你建议的问题是我认为如果milk.expiredAtundefinednew Date(milk.expiredAt) 会抛出错误。 (如果相反它返回undefined 它仍然不是我想要的,因为我不想将undefined 存储在我的数据库中,而且我不确定我什至可以在mongoDB 中)
  • 所以从const { expiredAt, ...preparedMilk } = milk开始。
  • @jonrsharpe 谢谢它确实以某种方式解决了它,如果我理解正确的话,按照你的建议我会做if (milk.expiredAt) preparedMilk['expiredAt'] = milk.expiredAt 因为我不能做preparedMilk.expiredAt = milk.expiredAt 因为在破坏环之后@987654349 @ 没有属性 expiredAt。仍然感觉有点“hacky”我希望有一个更好的打字稿解决方案不会试图绕过它,但仍然感谢它确实解决了我现在的问题我想不出更清洁的东西。

标签: javascript node.js typescript mongoose


【解决方案1】:

这对你有用吗?

interface MilkCarton {
    company: string;
    price: number;
    expiredAt?: string;
    // ...20 more properties
}

interface MilkCartonSchema {
    company: string;
    price: number;
    expiredAt?: Date;
    // ...20 more properties
}

const prepareMilkForDb = (milk: MilkCarton): MilkCartonSchema => {
    return {
        ...milk,
        expiredAt: milk.expiredAt == null ? undefined : new Date(milk.expiredAt)
    };
}

Typescript sandbox

注意:我把类改成了接口,不知道行不行?

【讨论】:

  • 感谢您的回答,它几乎可以工作,但我不希望 expiredAt 为空并作为空值插入数据库,如果没有给出,我不想插入它在请求中给我。我最终得到了与您对expiredAt: ...(milk.expiredAt && { expiredAt: new Date(milk.expiredAt) }) 建议的类似的东西,然后如果 milk.expiredAt 未定义,它根本不会将其添加到对象中。不幸的是,这并不是我想要的,它更像是一个创可贴,我有另一个对象,它有很多深度嵌套的日期属性,它太丑了。
  • @user3575645 你不能使用你原来的功能(然后从你的问题)并简单地添加一个类型preparedMilk?含义:const preparedMilk: MilkCartonSchema = { ...milk };(保留函数的其余部分)。
  • 如果我理解正确,那将不起作用,您建议的代码行会引发错误,指出我正在尝试将 string (milk.expiredAt) 分配给 Date (@987654329 @ 除外 expiredAtDate)。
  • @user3575645 你是 100% 正确的,别介意我?
  • @user3575645 最后一次尝试!您可以添加 if (result.expiredAt == null) delete result.expiredAt; 以将其从对象中删除。这甚至可能是一个实用功能,因为您提到在其他地方也需要它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-10
  • 2017-03-04
  • 2013-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-29
相关资源
最近更新 更多