无法访问对象的深层 properties/values
Can't access deep properties/values of object
所以下面是我的示例测试代码,用于实施更广泛的解决方案。我创建了一个“服务”对象,每个 属性 是服务名称,值为服务对象。每个服务对象都包含一个 属性 个“命令”,其值是一个命令对象(类)。
这些命令是通过 CLI 执行的,它总是 returns 一个字符串,然后将其拆分。数组的索引 0 将是服务名称,而索引 1 将是命令的名称。
// Example Classes
class A {
init() {
console.log('I Am A');
}
}
class B {
init() {
console.log('I Am B')
}
}
// Example Services Structure
export const services = {
service1: {
commands: {
a: A
}
},
service2: {
commands: {
b: B
}
}
}
// Type Declarations
export type Services = typeof services;
export type ServicesKeys = keyof Services;
// Testing
const input = (prompt('Choose a Service') || '').split(' ');
if (input.length !== 2) Deno.exit();
if (input[0] in services) {
const sKey = input[0] as ServicesKeys;
const service = services[sKey];
const commands = service.commands;
if (input[1] in commands) {
// Run into issues here as `keyof typeof commands` is `never`
new commands[input[1] as keyof typeof commands]();
}
}
在 new commands[input[1] as keyof typeof commands]();
之前一切正常,因为 keyof typeof commands
的类型设置为从不。我理解为 commands
不能有 a
和 b
所以 keyof 必须是 never
但我该如何处理这个?
您只需定义 services
对象的类型,就像下面的重构一样。如果你想限制结构的任何部分的键,你可以简单地用你的 union/enum/etc.
替换 string
注意:我提供了代码中使用的 Deno
命名空间 API 的替代品,以便您可以直接在浏览器中 运行 游乐场示例。
const Deno = {
exit (code: number = 0): never {
throw new Error(`Exited with code ${code}`);
}
};
// Example Classes
type Command = {
init (): void;
};
class A implements Command {
init () {
console.log('I Am A');
}
}
class B implements Command {
init () {
console.log('I Am B')
}
}
// Type Declarations
type Service = {
commands: {
[commandName: string]: new () => Command;
};
};
type Services = { [serviceName: string]: Service };
// Example Services Structure
const services: Services = {
service1: {
commands: {
a: A
}
},
service2: {
commands: {
b: B
}
}
}
// Testing
const input = (prompt('Choose a Service') || '').split(' ');
if (input.length !== 2) Deno.exit();
const [serviceName, commandName] = input;
let command: Command | undefined;
if (serviceName in services) {
const {commands} = services[serviceName];
if (commandName in commands) {
command = new commands[commandName]();
}
}
command ? command.init() : console.log('No match');
所以下面是我的示例测试代码,用于实施更广泛的解决方案。我创建了一个“服务”对象,每个 属性 是服务名称,值为服务对象。每个服务对象都包含一个 属性 个“命令”,其值是一个命令对象(类)。
这些命令是通过 CLI 执行的,它总是 returns 一个字符串,然后将其拆分。数组的索引 0 将是服务名称,而索引 1 将是命令的名称。
// Example Classes
class A {
init() {
console.log('I Am A');
}
}
class B {
init() {
console.log('I Am B')
}
}
// Example Services Structure
export const services = {
service1: {
commands: {
a: A
}
},
service2: {
commands: {
b: B
}
}
}
// Type Declarations
export type Services = typeof services;
export type ServicesKeys = keyof Services;
// Testing
const input = (prompt('Choose a Service') || '').split(' ');
if (input.length !== 2) Deno.exit();
if (input[0] in services) {
const sKey = input[0] as ServicesKeys;
const service = services[sKey];
const commands = service.commands;
if (input[1] in commands) {
// Run into issues here as `keyof typeof commands` is `never`
new commands[input[1] as keyof typeof commands]();
}
}
在 new commands[input[1] as keyof typeof commands]();
之前一切正常,因为 keyof typeof commands
的类型设置为从不。我理解为 commands
不能有 a
和 b
所以 keyof 必须是 never
但我该如何处理这个?
您只需定义 services
对象的类型,就像下面的重构一样。如果你想限制结构的任何部分的键,你可以简单地用你的 union/enum/etc.
string
注意:我提供了代码中使用的 Deno
命名空间 API 的替代品,以便您可以直接在浏览器中 运行 游乐场示例。
const Deno = {
exit (code: number = 0): never {
throw new Error(`Exited with code ${code}`);
}
};
// Example Classes
type Command = {
init (): void;
};
class A implements Command {
init () {
console.log('I Am A');
}
}
class B implements Command {
init () {
console.log('I Am B')
}
}
// Type Declarations
type Service = {
commands: {
[commandName: string]: new () => Command;
};
};
type Services = { [serviceName: string]: Service };
// Example Services Structure
const services: Services = {
service1: {
commands: {
a: A
}
},
service2: {
commands: {
b: B
}
}
}
// Testing
const input = (prompt('Choose a Service') || '').split(' ');
if (input.length !== 2) Deno.exit();
const [serviceName, commandName] = input;
let command: Command | undefined;
if (serviceName in services) {
const {commands} = services[serviceName];
if (commandName in commands) {
command = new commands[commandName]();
}
}
command ? command.init() : console.log('No match');