我正在开发一款金融应用程序,该应用程序具有“出价”(购买某物的提议)和“询问”(出售某物的提议)。
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.
,如果我不添加一些东西,那么扩展接口就没有意义了。
您可以使用类型别名:
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)