Typescript: создание объекта с сопоставленными свойствами из значений перечисления - PullRequest
2 голосов
/ 17 апреля 2020

Я ищу способ создания объекта со значениями, вычисляемыми во время компиляции из значений перечисления и предварительно определенных вызовов функций - в основном идея состоит в том, чтобы связать некоторые аргументы функции с ключами. Например, предположим, что у меня есть следующее:

enum LogLevel {
  error = 'error',
  warning = 'warning'
  info = 'info'
}

const log = (level: LogLevel, message: string) => {
  console.log(`Level: ${level}, Message: ${message}`);
}

Я ищу синтаксис вроде:

const logger = {
  [level in LogLevel]: (msg: string) => log(level, msg)
}

, который не работает (компиляция завершается с A computed property name must be of type 'string', 'number', 'symbol', or 'any'.)

Я бы хотел, чтобы это было функционально равно:

const logger = {
  [LogLevel.error]: (msg: string) => log(LogLevel.error, msg),
  [LogLevel.warning]: (msg: string) => log(LogLevel.warning, msg),
  [LogLevel.info]: (msg: string) => log(LogLevel.info, msg)
}

, чтобы я мог использовать его следующим образом:

logger.error("Bad things happened")
logger.warn("Help me")

Реальный вариант использования содержит много элементов в перечисление, и я бы предпочел не изменять объект каждый раз при добавлении новых. Я знаю, что могу по крайней мере добавить ограничение типа, которое потребовало бы присутствия всех ключей из перечисления в типе с очень похожим синтаксисом:

type Logger = {
  [level in LogLevel]: (msg: string) => void
}

, но так как значения являются повторяющимися и на самом деле просто шаблонными, я хотели бы, чтобы они генерировались автоматически.

1 Ответ

0 голосов
/ 17 апреля 2020

Единственное, что следует иметь в виду, это то, что TypeScript типы удаляются после компиляции до JavaScript, поэтому вам нужно динамически генерировать Logger.

const allLogLevels = ['error', 'warning', 'info'] as const;
type LogLevel = typeof allLogLevels[number]; // 'error' | 'warning' | 'info'

type Logger = {
  [level in LogLevel]: (msg: string) => void
}

const log = (level: LogLevel, message: string) => {
  console.log(`Level: ${level}, Message: ${message}`);
}

function createLogger() {
  const logger: Partial<Logger> = {};

  for (let key of allLogLevels) {
    logger[key] = (message: string) => log(key, message);
  }

  return logger as Logger;
}

// runtime
const logger = createLogger();

logger.error('test error.');
logger.warning('test warning.');
logger.info('test info.');

Пример TypeScript Playground здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...