Typescript 'tree' 对象定义
Typescript 'tree' object definition
我不太确定 'name' 是否适合我正在创建的对象类型。我称它为树是因为它看起来类似于没有关系的嵌套树。本质上我想要一个具有嵌套定义的对象
{
test1: OptionsInterface,
test2: {
test3: OptionsInterface,
test4: {
test5: OptionsInterface,
},
},
}
所以第一级可以是 OptionsInterface
或 {[s: string]: OptionsInterface}
有没有办法在对象的每个 'level' 上使用它?
我试过这样定义上面的内容:
export default class ApiClient {
constructor(options: {[s: string]: OptionsInterface | {[s: string]: OptionsInterface}}) {}
但这只会是 2 深,对吧?有没有一种方法可以定义我的示例对象而无需手动添加每个深度?
用例
我希望能够像这样称呼我的 class
api = new ApiClient(routeSchema);
await api.call('test2.test4.test5', params);
通话中:
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);
}
其中 callWithOptions
期望 OptionsInterface
当然可以。
type NestableOptionsInterface = OptionsInterface | { [k: string]: NestableOptionsInterface }
也就是说 NestableOptionsInterface
是一个 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
看起来不错。
如果你想保持实际构造函数参数的类型,你可以像这样使用泛型:
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}}}}}>
希望对您有所帮助。祝你好运!
我不太确定 'name' 是否适合我正在创建的对象类型。我称它为树是因为它看起来类似于没有关系的嵌套树。本质上我想要一个具有嵌套定义的对象
{
test1: OptionsInterface,
test2: {
test3: OptionsInterface,
test4: {
test5: OptionsInterface,
},
},
}
所以第一级可以是 OptionsInterface
或 {[s: string]: OptionsInterface}
有没有办法在对象的每个 'level' 上使用它?
我试过这样定义上面的内容:
export default class ApiClient {
constructor(options: {[s: string]: OptionsInterface | {[s: string]: OptionsInterface}}) {}
但这只会是 2 深,对吧?有没有一种方法可以定义我的示例对象而无需手动添加每个深度?
用例
我希望能够像这样称呼我的 class
api = new ApiClient(routeSchema);
await api.call('test2.test4.test5', params);
通话中:
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);
}
其中 callWithOptions
期望 OptionsInterface
当然可以。
type NestableOptionsInterface = OptionsInterface | { [k: string]: NestableOptionsInterface }
也就是说 NestableOptionsInterface
是一个 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
看起来不错。
如果你想保持实际构造函数参数的类型,你可以像这样使用泛型:
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}}}}}>
希望对您有所帮助。祝你好运!