我正在寻找一种生成对象的方法,该对象具有在编译期间根据枚举值和预定义的函数调用计算出的值-基本上,该想法是将函数的某些参数与键绑定。例如,假设我具有以下条件:
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
}
但是由于这些值是重复的且实际上只是样板,因此我希望它们是自动生成的。
答案 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。