打字稿:从枚举值生成具有映射属性的对象

时间:2020-04-17 07:58:26

标签: typescript

我正在寻找一种生成对象的方法,该对象具有在编译期间根据枚举值和预定义的函数调用计算出的值-基本上,该想法是将函数的某些参数与键绑定。例如,假设我具有以下条件:

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 :(得分:1)

这里唯一要记住的是,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示例为here

相关问题