以无缝方式使用打字稿联合
Use typescript unions in a seamless way
我说的后端有一个 API 来创建订单。
这样的订单是有商品的,客户端收到的时候只是ID指定,服务器发送的时候是完整的明细对象。
打字稿界面应该是这样的:
export interface Order {
userId: number;
bought_products: BoughtProduct[];
}
export interface BoughtProduct {
quantity: number;
product: number | Product; // not specified here
created?: string; // other keys are optional because only present if sent by Backend
}
如果 typescript 解释器能够理解我何时将产品用作数字或接收产品作为对象,而无需显式强制转换,那将是完美的。
这是因为,因为它是一个嵌套数组,所以使用强制转换会很复杂。
中看到一个更直接的问题示例
Typescript 足够聪明,如果您之前输入检查过它,它会自动为您转换它,例如
if (typeof boughtProduct.product === "number" {
// it will be handled as number
} else {
// it will be handled as Product
}
我会做这样的事情:
interface Order {
userId: number;
bought_products: Array<ClientBoughtProduct | ServerBoughtProduct>;
}
interface BoughtProduct<T> {
quantity: number;
product: T;
}
interface ClientBoughtProduct extends BoughtProduct<number> {}
interface ServerBoughtProduct extends BoughtProduct<Product> {
created: string;
}
然后我会使用 user defined type guards:
function isClientBoughtProduct(obj: BoughtProduct<any>): obj is ClientBoughtProduct {
return typeof obj.product === "number";
}
function isServerBoughtProduct(obj: BoughtProduct<any>): obj is ServerBoughtProduct {
return typeof obj.product === "object";
}
if (isServerBoughtProduct(obj)) {
// obj.created is available
}
我说的后端有一个 API 来创建订单。 这样的订单是有商品的,客户端收到的时候只是ID指定,服务器发送的时候是完整的明细对象。
打字稿界面应该是这样的:
export interface Order {
userId: number;
bought_products: BoughtProduct[];
}
export interface BoughtProduct {
quantity: number;
product: number | Product; // not specified here
created?: string; // other keys are optional because only present if sent by Backend
}
如果 typescript 解释器能够理解我何时将产品用作数字或接收产品作为对象,而无需显式强制转换,那将是完美的。
这是因为,因为它是一个嵌套数组,所以使用强制转换会很复杂。
Typescript 足够聪明,如果您之前输入检查过它,它会自动为您转换它,例如
if (typeof boughtProduct.product === "number" {
// it will be handled as number
} else {
// it will be handled as Product
}
我会做这样的事情:
interface Order {
userId: number;
bought_products: Array<ClientBoughtProduct | ServerBoughtProduct>;
}
interface BoughtProduct<T> {
quantity: number;
product: T;
}
interface ClientBoughtProduct extends BoughtProduct<number> {}
interface ServerBoughtProduct extends BoughtProduct<Product> {
created: string;
}
然后我会使用 user defined type guards:
function isClientBoughtProduct(obj: BoughtProduct<any>): obj is ClientBoughtProduct {
return typeof obj.product === "number";
}
function isServerBoughtProduct(obj: BoughtProduct<any>): obj is ServerBoughtProduct {
return typeof obj.product === "object";
}
if (isServerBoughtProduct(obj)) {
// obj.created is available
}