Mixin Type模式不起作用

时间:2018-03-18 23:52:44

标签: typescript

我正在为AWS的Step Function配置创建一个类型,并且可以组成函数的各种“状态”包括:{

export type StepFunctionState = IStepFunctionTask 
    & IStepFunctionChoice 
    & IStepFunctionWait;

我正在使用“mixin”模式,因此状态可以是不同类型状态的任意组合。各种州的定义是:

export interface IStepFunctionTask extends IStepFunctionBaseState {
  Type: "Task";
  /** of the format arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:${self:service}-${opt:stage}-FUNCTION_NAME */
  Resource: AwsFunctionArn;
  Next?: string;
  End?: true;
  Retry?: [
    {
      ErrorEquals: string[];
      IntervalSeconds: number;
      BackoffRate: number;
      MaxAttemps: number;
    }
  ];
  Catch?: [
    {
      ErrorEquals: string[];
      Next: string;
    }
  ];
}

export interface IStepFunctionChoice extends IStepFunctionBaseState {
  Type: "Choice";
  Choices: [
    {
      /** points to the specific area of context which is being evaluated in the choice */
      Variable: string;
      /** compare the value passed in -- and scoped by "Variable" -- to be numerically equal to a stated number */
      NumericEquals?: number;
      /** the next state to move to when completed with this one */
      Next?: string;
      /** the step-function should stop at this step */
      End?: boolean;
    }
  ];
}

export interface IStepFunctionWait extends IStepFunctionBaseState {
  Type: "Wait";
  Seconds: number;
  Next: AwsFunctionArn;
}

其中IStepFunctionBaseState只是加强了所需的Type属性,这是歧视联盟的关键部分:

export interface IDictionary<T = any> {
  [key: string]: T;
}
export type IStepFunctionType = "Task" | "Wait" | "Choice";
export interface IStepFunctionBaseState {
  Type: IStepFunctionType;
}

然后,我可以为每个任务类型分配合理的数据结构:

const wait: IDictionary<IStepFunctionWait> = {
  yyy: {
    Type: "Wait",
    Seconds: 12,
    Next: "foo"
  }
};

const task: IDictionary<IStepFunctionTask> = {
  xxx: {
    Type: "Task",
    Resource: "arn",
    Next: "x2"
  },
  x2: {
    Type: "Task",
    Resource: "arn2",
    End: true
  }
};

const pass: IDictionary<IStepFunctionPass> = {
  pass: {
    Type: "Pass",
    Result: {
      foo: 1,
      bar: 2
    },
    ResultPath: "$.info",
    Next: "baz"
  }
};

const choice: IDictionary<IStepFunctionChoice> = {
  zzz: {
    Type: "Choice",
    Choices: [
      {
        Variable: "$.bar",
        NumericEquals: 1,
        Next: "xxx"
      }
    ]
  }
};

这一切都有效,但不起作用的是以下内容:

const mixedBag: IDictionary<StepFunctionState> = {
  ...task,
  ...choice,
  ...wait
};

我抱怨mixedBag的定义出现了一些错误:

  

输入'{Type:“Task”;资源:字符串;下一个?:字符串;结束?:是的;重试?:[{ErrorEquals:string []; In ...'不能分配给'{Type:“Task”;资源:字符串;下一个?:字符串;结束?:是的;重试?:[{ErrorEquals:string [];在...'。存在两种具有此名称的不同类型,但它们是不相关的。

以及

  

类型'{Type:“Choice”中缺少属性'资源';选择:[{变量:字符串; NumericEquals?:数字;下一个?:字符串;结束?:布尔......'。

enter image description here

希望这是人们帮助的足够背景,但如果您需要更多,请告诉我。

1 个答案:

答案 0 :(得分:1)

问题是当你希望对象拥有联合中的所有属性时使用intersection types (&)(因此所有步骤都具有IStepFunctionTaskIStepFunctionChoice和{的所有属性{1}}所有的同时)。显然,任务可以是IStepFunctionWaitIStepFunctionWaitIStepFunctionChoice,可以使用联合类型(IStepFunctionTask)建模

|