打字稿不允许使用默认

时间:2021-03-27 15:51:33

标签: typescript

我有两种类型,一种包含名为 amount 的属性,另一种不包含。 我想从一个或另一个中解构该属性,以提供一个默认值,以防它不存在(不包含它的类型)。 这是有效的 JS 代码,但是 typescript 抱怨其中一种类型中不存在此类属性,这是正确的,但这就是默认值的用途。

代码如下:

interface A {
  amount: number;
  name: string;
}

type notA = {
  name: string
}

const values = new Map<string, A>()
values.set('test', {name: 'test', amount: 0})
const defaultValue = {name: 'no-test'}

const { amount = 0 } = values.get('tust') || defaultValue

console.log(name, amount)

我知道打字稿试图保护我免受此类属性存在的类型不正确,但从一开始就不应该这样做。 这可能是因为 typescript 没有确切的类型,它允许将额外的 props 附加到没有定义它们的类型,所以我怎样才能使上面的编译?

2 个答案:

答案 0 :(得分:0)

有多种方法可以处理这种情况。这是快速的方法

const defaultValue = { name: 'no-test' } as A

检查链接:Typescript playground

答案 1 :(得分:0)

我非常倾向于重构为以下内容:

const { amount } = values.get('tust') || { name: "no-test", amount: 0 };

因为您的意图大概是应该有一个 A 类型的默认值,特别是如果您打算使用 0 作为 amount 属性的默认值。


但是,假设你不能改变它,我建议给 defaultValue 一个显式注释的类型。当你让编译器推断它的类型时,它变成了 {name: string}。就其本身而言,这种类型是正确的,但它根本不暗示 amount 属性的任何内容(如您所见,TypeScript 中的对象类型并不准确)。如果您希望编译器了解 defaultValue 可能缺少 amount 属性,则需要将其注释为此类类型。例如:

interface MaybeA {
  amount?: number;
  name: string;
}
const defaultValue: MaybeA = { name: 'no-test' }

我已经声明了一个 MaybeA 接口,它是 A 的更广泛版本,其中 amount 属性是 optional,所以它的类型是 numberundefined。然后,这将按需要工作:

const { amount = 0 } = values.get('tust') || defaultValue // no error

您也可以改写 NotA 类型,它肯定缺少 amount 属性:

interface NotA {
  amount?: undefined;
  name: string;
}
const defaultValue: NotA = { name: 'no-test' }
const { amount = 0 } = values.get('tust') || defaultValue // also okay

当然,没有什么要求您实际为这些类型命名,特别是如果您只使用它们一次:

const defaultValue: { name: string, amount?: undefined } = { name: 'no-test' }
const { amount = 0 } = values.get('tust') || defaultValue // okay

Playground link to code