【问题标题】:Can't access deep properties/values of object无法访问对象的深层属性/值
【发布时间】:2021-11-23 05:18:08
【问题描述】:

所以下面是我的示例测试代码,以实现更广泛的解决方案。我创建了一个“服务”对象,每个属性都是服务名称,值是服务对象。每个服务对象都拥有一个“命令”属性,其值是命令对象(类)。

这些命令是通过 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](); 作为keyof typeof commands 的类型设置为从不之前,一切基本上都可以正常工作。我理解为 commands 不能有 ab 所以 keyof 必须是 never 但我该如何处理呢?

【问题讨论】:

  • 您的目标是让命令具有任意字符串作为键,或者特别是 a、b、...?即命令:{[key: string]: A|B}{a: A} | {b: B}

标签: javascript typescript types deno


【解决方案1】:

您只需要定义services 对象的类型,就像下面的重构一样。如果你想限制结构任何部分的键,你可以简单地将string 替换为你的 union/enum/etc。

注意:我为您的代码中使用的 Deno 命名空间 API 提供了一个替代品,以便您可以直接在浏览器中运行 Playground 示例。

TS Playground link

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');

【讨论】:

  • 太棒了,谢谢。不是复制/粘贴工作,但最终以您的示例为参考设法使其工作。
猜你喜欢
  • 2017-01-26
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
  • 2019-12-06
  • 2019-09-14
相关资源
最近更新 更多