A continuación se muestra mi código de prueba de ejemplo para implementar en la solución más amplia. Creé un objeto de "servicios", cada propiedad es el nombre del servicio y el valor es el objeto del servicio. Cada objeto de servicio tiene una propiedad de "comandos" con el valor de ser un objeto de comandos (clases).
Estos comandos se ejecutan a través de la CLI, que siempre devuelve una cadena que luego se divide. el índice 0 de la matriz sería el nombre del servicio, mientras que el índice 1 sería el nombre del comando.
// 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](); } } Esencialmente, todo funciona bien hasta que los new commands[input[1] as keyof typeof commands](); ya que el tipo de keyof typeof commands se establece en nunca. Lo que entiendo es que los commands no pueden tener a AND b , por lo que keyof never debe ser, pero ¿cómo trabajo con esto?
Solo necesita definir el tipo para su objeto de services , como en el refactor a continuación. Si desea restringir las claves para cualquier parte de la estructura, simplemente puede reemplazar la string con su unión/enum/etc.
Nota: Proporcioné un sustituto para las API de espacio de nombres de Deno utilizadas en su código para que pueda ejecutar el ejemplo del patio de recreo directamente en su navegador.
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');