两个相同的 TypeScript 接口但名称不同 - 如何使其干燥/避免重复?

问题描述 投票:0回答:1

我正在开发一款金融应用程序,该应用程序具有“出价”(购买某物的提议)和“询问”(出售某物的提议)。

interface Ask {
  price: number
  amount: number
}

interface Bid {
  price: number
  amount: number
}

如何避免重复两个相同的类型定义? (它们总是相同的) 我可以只有一个界面并称之为

Offer
,但它失去了意义和清晰度。

我试过这个:

interface Offer {
  price: number
  amount: number
}

interface Bid extends Offer {}
interface Ask extends Offer {}

但是我收到一个 eslint 错误,提示

An interface declaring no members is equivalent to its supertype.
,如果我不添加一些东西,那么扩展接口就没有意义了。

typescript types dry
1个回答
2
投票

您可以使用类型别名:

interface Ask {
    price: number;
    amount: number;
}

type Bid = Ask;

游乐场链接

请注意,由于 TypeScript 的类型系统是 structural(基于类型的 shape),而不是 nominative(基于类型的名称/标识),因此类型为

Ask
的对象将可分配给
Bid 
变量/属性/参数,反之亦然。 TypeScript 不区分它们:

let a1: Ask = { price: 42, amount: 2 };
//  ^? −−− let a1: Ask
let b1: Bid = { price: 67, amount: 4 };
//  ^? −−− let b1: Ask
a1 = b1; // <== This is allowed

请注意,

b1
显示的类型提示是
Ask
,而不是
Bid

如果您愿意,您可以通过品牌化来区分类型:

interface Offer {
    price: number;
    amount: number;
}

interface Bid extends Offer {
    __type__: "Bid";
}

interface Ask extends Offer {
    __type__: "Ask";
}

游乐场链接

那么 TypeScript 将不允许它们之间进行赋值:

let a1: Ask = { price: 42, amount: 2, __type__: "Ask"};
//  ^? −−− let a1: Ask
let b1: Bid = { price: 67, amount: 4, __type__: "Bid"};
//  ^? −−− let b1: Bid
a1 = b1; // <== Error: Type 'Bid' is not assignable to type 'Ask'.
         //              Types of property '__type__' are incompatible.
         //                Type '"Bid"' is not assignable to type '"Ask"'.(2322)

缺点是您必须真正拥有该属性(如上所述),或者在创建具有这些类型的对象时最初使用类型断言。

我更喜欢真正拥有这些属性(以便在调试器等中轻松区分它们),但有时这可能不是您想要的。要使用类型断言,我会将其封装在一个函数中,也许:

// ...
let a1 = makeAsk({ price: 42, amount: 2 });
//  ^? −−− let a1: Ask
let b1 = makeBid({ price: 67, amount: 4 });
//  ^? −−− let b1: Bid
a1 = b1; // <== Error: Type 'Bid' is not assignable to type 'Ask'.
         //              Types of property '__type__' are incompatible.
         //                Type '"Bid"' is not assignable to type '"Ask"'.(2322)

游乐场链接

© www.soinside.com 2019 - 2024. All rights reserved.