TS - 定义不能同时包含错误和有效负载字段的接口

时间:2017-08-11 09:31:23

标签: typescript interface

我有一个Action类型:

  1. 必须包含字段type {String}
  2. CAN 包含字段payload {Object<string, any>}
  3. CAN 包含字段error {Error}
  4. 约束

    • IF contains field payload THEN it cannot contain field error
    • IF contains field error THEN it cannot contain field payload

    这就是我所做的:

    interface ActionBase {
      type: string
    }
    
    interface ActionError extends ActionBase {
      error: Error
    }
    
    interface Action extends ActionBase {
      payload?: Object<string, any>
    }
    

    外部资源:DefinitelyTyped/types/redux-actions/index.d.ts/#L14

    现在我想知道是否存在一种方法只定义一个实现所有这一切的Action 接口。

    如何实现所描述的内容?

    注意:问题直接关于Typescript,但由于这个问题,任何关于实现接口的语言的答案都将受到赞赏。

2 个答案:

答案 0 :(得分:1)

不,不可能。我的意思是接口的整个概念是统一共同的行为。如果要区分结构,则必须像使用多个接口一样使用。

答案 1 :(得分:1)

是的,你可以这样做,主要是。

TypeScript缺少exact types,这是你想要用来说一个对象有一些属性而没有其他属性的东西。

但在这种情况下,您要禁用特定的属性。如果您将它们指定为具有never类型,则无法将它们放入(never是一种没有值的特殊类型)。如果你让它们成为可选项,那么可以将它们排除在外。因此,never类型的可选属性是您必须忽略的属性。以下是您的示例实现:

interface ActionBase {
  type: string
}
interface ActionError extends ActionBase {
  error: Error;
  payload?: never;
}
interface ActionPayload extends ActionBase {
  payload: Record<string, any>;
  error?: never;
}
interface ActionNeither extends ActionBase {
  payload?: never;
  error?: never;
}
type Action = ActionError | ActionPayload | ActionNeither;

因此Action可以有errorpayload或两者都没有,但不能同时拥有两者。让我们看看它有效:

var a: Action = {
  type: 'thing',
}; // okay, just a type

var a: Action = {
  type: 'thing',
  payload: {'dog': 123}
}; // okay, with payload

var a: Action = {
  type: 'thing',
  error: new Error(),
}; // okay, with error

var a: Action = {
  type: 'thing',
  error: new Error(),
  payload: {'dog': 123}
}; // error! can't do both error and payload

我认为这或多或少都是你想要的。请注意以下问题:

var a: Action = {
  type: 'thing',
  monkey: 12
}; // error, object literal doesn't like extra properties

var a: Action = {
  type: 'thing',
  error: undefined,
  payload: {'dog': 123}
}; // okay, undefined is considered "missing", best we can do with optionals 

我说你可以“大部分”只是因为可选属性总是设置为undefined,所以没有什么能阻止ActionPayload拥有 undefined {{ 1}}而不是缺席 error。但这几乎是一样的,至少根据TypeScript。

希望有所帮助。祝你好运!