TypeScript接口,允许其他属性

Aar*_*all 31 typescript

总之,是否可以使用一个声明某些基本属性的接口,但不限制其他属性?这是我目前的情况:

我正在使用Flux模式,它定义了一个通用调度程序:

class Dispatcher<TPayload> {
    dispatch(arg:TPayload):void { }
}
Run Code Online (Sandbox Code Playgroud)

然后我创建一个具有自己的有效负载类型的调度程序,如下所示:

interface ActionPayload {
    actionType: string
}

const dispatcher = new Dispatcher<ActionPayload>();
Run Code Online (Sandbox Code Playgroud)

现在我有一些动作代码应该用一些额外的数据调度有效载荷,但ActionPayload接口只允许actionType.换句话说,这段代码:

interface SomePayload extends ActionPayload {
    someOtherData: any
}

class SomeActions {
    doSomething():void {
        dispatcher.dispatch({
            actionType: "hello",
            someOtherData: {}
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

出现编译错误,因为someOtherDataActionPayload接口不匹配.问题是许多不同的"动作"类会重复使用同一个调度程序,所以虽然它在someOtherData这里可能会anotherKindOfData在那里,依此类推.目前,我所能做的就是使用它,new Dispatcher<any>()因为会发送不同的动作.ActionPayload但是,所有操作共享一个基础,所以我希望能够限制类型new Dispatcher<extends ActionPayload>()或类似的东西.有可能吗?

Seb*_*ien 75

如果您希望ActionPayload接受任何其他属性,您可以添加索引器:

interface ActionPayload {
    actionType: string,
    [x: string]: any 
}
Run Code Online (Sandbox Code Playgroud)

请参阅https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#strict-object-literal-assignment-checking

  • 遗憾的是,如果我们添加其他类型的字段(例如拥有一个 Date 属性和动态字符串属性),则这不起作用 (4认同)
  • 类型:“未知”会比“任何”更好。 (2认同)

zlo*_*ctb 13

interface Options {
  darkMode?: boolean;
  [otherOptions: string]: unknown;
  }
Run Code Online (Sandbox Code Playgroud)


mPr*_*inC 7

使用 TypeScript 3.9+ 并strict设置为truein tsconfig.json,我收到接受答案的错误。

这是解决方案:


interface ActionPayload {
    actionType: string;

    // choose one or both depending on your use case
    // also, you can use `unknown` as property type, as TypeScript promoted type, 
    // but it will generate errors if you iterate over it
    [x: string]: any;
    [x: number]: any;
}
Run Code Online (Sandbox Code Playgroud)

这可以避免以下错误:

  • An index signature parameter type must be either 'string' or 'number'.
    • symbol不允许
  • An index signature parameter type cannot be a union type. Consider using a mapped object type instead.
    • string | number不允许进入[x: string | number]: unknown;