代码之家  ›  专栏  ›  技术社区  ›  user1283776

当使用扩展时,typescript是否可以像使用联合时一样推断开关块中的正确类型?

  •  1
  • user1283776  · 技术社区  · 5 年前

    typescript推断 serverMessage 正确地作为 ServerInformation 在以下情况下:

    export interface IServerResponse {
        type: 'response';
        cmd: string;
    }
    
    export interface ServerError {
        type: 'error',
        errorcode: string;
        cmd?: string;
        trans_id?: string;
        data?: Object;
    }
    
    export interface ServerInformation {
        type: 'information',
        info: string;
        data?: Object;
    }
    
    export type ServerMessage = IServerResponse | ServerError | ServerInformation;
    
    let serverMessage = message as ServerMessage;
    
    switch (serverMessage.type) {
        case 'information':
            const information: Information = serverMessage.info; // type is inferred correctly
            break;
    

    但在我看来,它更符合我在其他地方用来扩展不同类型消息的类语法。 IServerMessage 比把它们组合成 ServerMessage 类型:

    能做到吗?我在下面的尝试失败。

    export interface IServerMessage {
        type: string;
    }
    
    export interface IServerResponse extends IServerMessage {
        type: 'response';
        cmd: string;
    }
    
    export interface ServerError extends IServerMessage {
        type: 'error',
        errorcode: string;
        cmd?: string;
        trans_id?: string;
        data?: Object;
    }
    
    export interface ServerInformation extends IServerMessage {
        type: 'information',
        info: string;
        data?: Object;
    }
    
    let serverMessage: IServerMessage = message ;
    
    switch (serverMessage.type) {
        case 'information':
            const information: Information = serverMessage.info; // type is still inferred as ServerMessage, not the more specific InformationMessage
            break;
    
    1 回复  |  直到 5 年前
        1
  •  1
  •   Titian Cernicova-Dragomir    5 年前

    TL;DR 不,你需要一个工会。

    switch语句在第一种情况下工作的原因是您有一个歧视性的联合。由于已知和有限的可能类型列表,开关可以根据检查缩小联合的类型。

    在第二种情况下 IServerMessage 是一个可以从任何地方通过任何类型实现的接口。因此,typescript没有要缩小范围的详尽列表,因此不会进行任何缩小。