当第一个参数是来自接口的键时,动态确定第二个参数

时间:2019-03-21 17:01:38

标签: typescript typescript-typings

我有一个类似的接口,因此作为选项传递给模块工厂函数:

interface FactoryOpts {
  name?: string
  radius?: number
  // many more entries...
}

例如:

factory({ radius: 10 })

然后,我有一个定义出厂值的接口。它有一些功能,但是我坚持使用的一个功能叫做“选项”,看不到如何避免使用“任何”:

interface ReturnedFactoryInstance {
  // I don't want to use "any" for the value, but I also don't
  // want to write a method for each options
  option(name: keyof FactoryOpts, value: any) => void
}

interface Factory {
  someProps: string
  (selector: HTMLElement|String, options: FactoryOpts): ReturnedFactoryInstance
}

是否可以动态确定值的类型?例如:

const instance = factory({ radius: 10 })

// Correct - this will compile
factory.option('radius', 10)

// Error - this will not compile
factory.option('radius', 'some string')

FactoryOpts中的每个条目创建一个函数是实现此目标的唯一方法吗?

使用Karol的建议的解决方案:

interface FactoryOpts {
  name?: string
  radius?: number
  // many more entries...
}

interface Factory {
  someProps: string
  (selector: HTMLElement|String, options: FactoryOpts): ReturnedFactoryInstance<FactoryOpts>
}

interface ReturnedFactoryInstance<ValidOptions> {
  option: <Key extends keyof ValidOptions>(property: Key, value: ValidOptions[Key]) => void
}

然后您可以导出Factory,例如declare const f: Factory等。

1 个答案:

答案 0 :(得分:2)

interface Factory<T> {
  option<K extends keyof T>(this: Factory<T>, name: K, value: T[K]): void;
}

type FactoryConstructor = <T>(arg: T) => Factory<T>;

用法:

declare const factory: FactoryConstructor;

factory({ radius: 10 }).option('radius', 1);

请参见TypeScript Playground