#javascript #typescript #types #deno
Вопрос:
Итак, ниже приведен мой пример кода тестирования для внедрения в более широкое решение. Я создал объект «услуги», каждое свойство-это имя службы, значение которого является объектом службы. Каждый объект службы содержит свойство «команды», значение которого является объектом команд (classe).
Эти команды выполняются через интерфейс командной строки, который всегда возвращает строку, которая затем разделяется. индекс 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
as не установлен в никогда. Которого, как я понимаю, commands
не может быть a
, И b
поэтому ключ должен быть never
, но как мне с этим работать?
Комментарии:
1. ваша цель, чтобы команды имели произвольные строки в качестве ключей или, в частности, a, b,…? команды ie:
{[key: string]: A|B}
или{a: A} | {b: B}
Ответ №1:
Вам просто нужно определить тип для вашего services
объекта, как в приведенном ниже рефакторе. Если вы хотите ограничить ключи для любой части структуры, вы можете просто 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');
Комментарии:
1. Потрясающе, спасибо за это. Это не была работа по копированию/вставке, но в конце концов ей удалось заставить ее работать с вашим примером в качестве ссылки.