需求示例:
一个HTTP请求参数类型,用于创建会议。
会议可以为音频、或者视频,所以参数类型要么为音频会议的类型、要么为视频会议的类型,剩下的是两种会议共有的参数。
开始的想法:
interface VideoConferenceRoom {
mode: "VIDEO";
layout: 1 | 2 | 3 | 4 | 6 | 9;
bitrate: number;
framerate: number;
resolution: "CIF" | "QCIF" | "VGA" | "SVGA" | "XVGA" | "HD720" | "QVGA";
}
interface AudioConferenceRoom {
mode: "AUDIO";
}
interface CreateConferenceRoomParams
extends VideoConferenceRoom,
AudioConferenceRoom {
extension_number: string;
room_pin: string;
admin_pin: string;
subject: string;
language: string;
custom_options: string;
outbound_caller_ids: { provider_id: string; caller_id: string }[];
}
error: Interface 'CreateConferenceRoomParams' cannot simultaneously extend types 'VideoConferenceRoom' and 'AudioConferenceRoom'.
Named property 'mode' of types 'VideoConferenceRoom' and 'AudioConferenceRoom' are not identical.
失败,因为interface
的多重继承需要被继承的接口完全一致,而此处的两个接口的mode
字段并不兼容。
那么我们需要一个Unit types
的中间类型:
......省略......
// 新增
type ConferenceRoom = AudioConferenceRoom | VideoConferenceRoom;
interface CreateConferenceRoomParams
extends ConferenceRoom {
extension_number: string;
room_pin: string;
admin_pin: string;
subject: string;
language: string;
custom_options: string;
outbound_caller_ids: { provider_id: string; caller_id: string }[];
}
error: An interface can only extend an object type or intersection of object types with statically known members.
失败,接口只能继承一个静态类型,而联合类型是不确定的。那么最后的:
interface VideoConference {
mode: "VIDEO";
layout: 1 | 2 | 3 | 4 | 6 | 9;
bitrate: number;
framerate: number;
resolution: "CIF" | "QCIF" | "VGA" | "SVGA" | "XVGA" | "HD720" | "QVGA";
}
interface AudioConference {
mode: "AUDIO";
}
type ConferenceMedia = VideoConference | AudioConference;
export type CreateConferenceRoomParams = ConferenceMedia & {
extension_number: string;
room_pin: string;
admin_pin: string;
subject: string;
language: string;
custom_options: string;
outbound_caller_ids: { provider_id: string; caller_id: string }[];
};
使用类型别名来实现,将两个类型交叉后,得到一个符合需求的类型组合。
顺便类型名称改了一下,变得更符合语义