javascript - 无法访问对象的深层属性/值
问题描述
所以下面是我的示例测试代码,以实现更广泛的解决方案。我创建了一个“服务”对象,每个属性都是服务名称,值是服务对象。每个服务对象都拥有一个“命令”属性,其值是命令对象(类)。
这些命令通过 CLI 执行,该 CLI 始终返回一个字符串,然后将其拆分。数组的索引 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]();
在as 的类型keyof typeof commands
设置为 never之前,一切基本上都可以正常工作。我理解commands
不能拥有a
,b
所以 keyof 必须是,never
但我该如何处理呢?
解决方案
您只需要为您的services
对象定义类型,就像在下面的重构中一样。如果你想限制结构任何部分的键,你可以简单地string
用你的 union/enum/etc 替换。
注意:我提供了代码中使用的命名空间 API 的替代品,Deno
以便您可以直接在浏览器中运行 Playground 示例。
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');
推荐阅读
- python - tmp 文件夹在 s3 存储桶中创建 [Errno 2] 没有这样的文件或目录:'/tmp/plain_file/7A50-99D2-24D9-42BF.tar':FileNotFoundError
- c++ - c++ std::vector 作为类方法的参数传递的函数
- python - 烧瓶运行无法识别 Windows 上的 python-dotenv
- excel - 使用多个条件计数
- sparql - 不一致的维基数据查询结果
- angular - angular 7 有 oboe.js 替代品吗?
- sql - 数据库中已经有一个名为 '' 的对象
- opencv - 仅检测二值图像中的垂直线
- python-3.x - 为什么最后一个子图中没有图表?
- tomcat - 通过 systemctl 在 CentOS 7 上使用端口 80 启动 tomcat 9