Typescript“树”对象定义

sou*_*rri 1 definition typescript

我不太确定我正在创建的对象类型的“名称”。我称其为树,因为它看起来类似于没有关系的嵌套树。本质上我想要一个具有嵌套定义的对象,如下所示

{
    test1: OptionsInterface,
    test2: {
        test3: OptionsInterface,
        test4: {
            test5: OptionsInterface,
        },
    },
}
Run Code Online (Sandbox Code Playgroud)

因此,第一个级别可以是OptionsInterface或者{[s: string]: OptionsInterface}有没有办法在对象的每个“级别”上使用它?

我尝试像这样定义上面的内容:

export default class ApiClient {
    constructor(options: {[s: string]: OptionsInterface | {[s: string]: OptionsInterface}}) {}
Run Code Online (Sandbox Code Playgroud)

但这只会是 2 深,对吗?有没有一种方法可以定义我的示例对象,而无需手动添加每个深度?

用例

我希望能够像这样打电话给我的班级

api = new ApiClient(routeSchema);
await api.call('test2.test4.test5', params);
Run Code Online (Sandbox Code Playgroud)

通话中:

async call(config: string, variables: object = {}): Promise<Response> {
  const options = get(this.configuration, config);

  if (options === undefined) {
    throw new ConfigNotDefinedExpection(config);
  }

  return await this.callWithOptions(options, variables);
}
Run Code Online (Sandbox Code Playgroud)

哪里callWithOptions期望OptionsInterface

jca*_*alz 5

当然,你可以这样做。

type NestableOptionsInterface = OptionsInterface | { [k: string]: NestableOptionsInterface }
Run Code Online (Sandbox Code Playgroud)

这表示 aNestableOptionsInterface是一个OptionsInterface或 一个字典,其键是您想要的任何内容,其值是NestedOptionsInterface。所以这是一个递归定义。我们来测试一下:

class Foo {
  constructor(options: NestableOptionsInterface) { }
}

declare const optionsInterface: OptionsInterface;

new Foo(optionsInterface); // okay
new Foo({ a: optionsInterface, b: { c: optionsInterface } }); // okay
new Foo({ a: { b: { c: { d: { e: optionsInterface } } } } }); // okay
new Foo("whoops"); // error
new Foo({ a: optionsInterface, b: { c: "whoops" } }); // error
Run Code Online (Sandbox Code Playgroud)

看起来不错。

如果您想维护实际构造函数参数的类型,可以使用如下泛型:

class Foo<O extends NestableOptionsInterface> {
  constructor(options: O) { }
}

declare const optionsInterface: OptionsInterface;

new Foo(optionsInterface); // Foo<OptionsInterface>
new Foo({ a: optionsInterface, b: { c: optionsInterface } }); // Foo<{ a: OptionsInterface, b:{c: OptionsInterface}}>
new Foo({ a: { b: { c: { d: { e: optionsInterface } } } } }); // Foo<{ a:{b:{c:{d:{e: OptionsInterface}}}}}>
Run Code Online (Sandbox Code Playgroud)

希望有帮助。祝你好运!