我有一个Action
类型:
type
{String
} payload
{Object<string, any>
} error
{Error
} 约束:
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,但由于这个问题,任何关于实现接口的语言的答案都将受到赞赏。
答案 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
可以有error
或payload
或两者都没有,但不能同时拥有两者。让我们看看它有效:
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。
希望有所帮助。祝你好运!