首页 > 解决方案 > 如何在 TypeScript 中正确使用扩展实例?

问题描述

我使用 TypeScript,但仍然有很多困惑。

我创建了一个这样的实例:

interface Product {
  type: 'free'|'pay';
  price?: number;
}

我将 price 设置为可选属性的原因是因为我只想在类型为“pay”时才将其设为有效属性。

因此,我想创建一个这样的界面:

interface Product {
  type: 'free'|'pay';
}

interface PayProduct extends Product {
  type: 'pay';
  price: number;
}

我想像这样使用它。

const loggingPrice = (product: Product) => {
  if (product.type !== 'pay') return;
  // product is definitely PayProduct.
  const { price } = product;
  console.log(price);
}

但是,当然,它会返回如下错误: TS2339: Property 'price' does not exist on type 'Product'.

这就是我使用类型断言的原因。

interface Product {
  type: 'free'|'pay';
}

interface PayProduct extends Product {
  type: 'pay';
  price: number;
}

const loggingPrice = (product: Product) => {
  if (product.type !== 'pay') return;
  // product is definitely PayProduct.
  const { price } = product as PayProduct;
  console.log(price);
}

我想不出别的办法。

我认为这是一个不好的方法。我真的不喜欢类型断言。(我觉得我在骗输入检查器。)

使用这些定义的接口的最佳方式是什么?

我为我糟糕的英语水平道歉。(我依赖自动翻译。)但是我很好奇是否有办法正确使用这些接口。

标签: typescripttypesinterfaceassertionunion-types

解决方案


不要延长。而是创建两种类型的可区分联合。现在它是一个或另一个(不可能只是一个基本接口实例)。测试product.type !== 'pay'将正确缩小。

https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions

interface PayProduct {
  type: 'pay';
  price: number;
}

interface FreeProduct {
  type: 'free';
}

type Product = PayProduct | FreeProduct;

const loggingPrice = (product: Product) => {
  if (product.type !== 'pay') return;
  // product is definitely PayProduct.
  const { price } = product;
  console.log(price);
}

游乐场链接


推荐阅读