TypeScript能够根据另一个参数来调整参数吗?

时间:2018-10-08 19:47:16

标签: typescript

我的程序包支持多个加载程序,实现了LoaderInterface

// tslint:disable-next-line:no-empty-interface
export interface LoaderOptions { }

export interface LoaderInterface {
  load(options: LoaderOptions): Object;
}

export interface SimpleLoaderOptions extends LoaderOptions {
  option1: string;
}
export interface AdvancedLoaderOptions extends LoaderOptions {
  option2: string;
}

MyModule入口点应接受两个选项:

  • loaderLoaderInterface(具体类)的实例
  • options对象巫婆应“匹配”相应的加载器选项

我的问题是我不知道如何在两个选项之间创建“连接”。

我需要类似的内容:如果loader是这样,则options应该看起来像这样。可能吗?


解决方案1:愚蠢的,因为有人可以将任何东西传递给options参数:

class MyModule {
  static create(loader: LoaderInterface, options: any) { }
}

解决方案2:也很愚蠢,因为允许任何形状为LoaderOptions的物体(基本上是任何物体):

class MyModule {
  static create(loader: LoaderInterface, options: LoaderOptions) { }
}

MyModule.create(new SimpleLoader, { foo: 'bar' })

解决方案3:更好,但仍然可以“混合”选择。但是带有自定义选项的自定义加载程序呢?

class MyModule {
  static create(loader: LoaderInterface, options: SimpleLoaderOptions
    | AdvancedLoaderOptions) { }
}

MyModule.create(new SimpleLoader, { option1: 'foo', option2: 'bar' })

1 个答案:

答案 0 :(得分:4)

您可以使加载程序接口通用。实现加载程序时,它将指定它支持的选项作为通用参数。 create方法将是通用的,将对加载程序的类型参数和选项对象使用相同的类型参数,从而在它们之间建立链接

export interface LoaderOptions { }

export interface LoaderInterface<T extends LoaderOptions> {
    load(options: T): Object;
}

export interface SimpleLoaderOptions extends LoaderOptions {
    option1: string;
}
export interface AdvancedLoaderOptions extends LoaderOptions {
    option2: string;
}

class MyModule {
    static create<T extends LoaderOptions>(loader: LoaderInterface<T>, options: T & {}) {
    }
}

class LoaderAdvanced implements LoaderInterface<AdvancedLoaderOptions> {
    load(options: AdvancedLoaderOptions): Object {
        return null as any;
    }
}

let m = MyModule.create(new LoaderAdvanced(), {
    option2: '' // required since we need AdvancedLoaderOptions
});

Playground link

注意:我们将T&{}用作options参数,以降低此推理站点的优先级,确保Tloader参数决定不是options