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

为什么在这种情况下类型缩小会失败?

  •  1
  • mikeysee  · 技术社区  · 6 年前

    鉴于:

    export type CommandsTypes = {
      "test-command": {
        propA: string;
        propB: number;
      };
    
      "test-command2": {
        propC: string;
        propD: number;
      };
    };
    
    export type Command<K extends keyof CommandsTypes> = {
      type: K;
      payload: CommandsTypes[K];
    };
    
    export type AnyCommand = Command<keyof CommandsTypes>;
    

    为什么以下类型没有按预期缩小:

    function handle(command: AnyCommand) {
      if (command.type === "test-command") {
        // I would expect the type of command at this point to be
        // Command<"test-command"> 
        // But its not?
      }
    }
    

    你知道为什么字体不能缩小 AnyCommand 在上面键入到 Command<"test-command"> ?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Titian Cernicova-Dragomir    6 年前

    Command<keyof CommandTypes> 相当于 { type: keyof CommandTypes, payload :CommandTypes[keyof CommandTypes] } 基本上这意味着您可以将任何类型与任何负载配对,这不是您想要的。

    你想建立一个歧视性的联盟。为此,我们可以使用条件类型的分布行为,该行为将对键并集的每个成员应用类型转换

    export type AnyCommandHelper<T extends keyof CommandsTypes> =
        T extends keyof CommandsTypes? Command<T>: never
    export type AnyCommand = AnyCommandHelper<keyof CommandsTypes>;