typescript - 使用 Enum 填充字段的通用工厂
问题描述
我不知道如何让这个工厂createLetterMap
为其实例生成默认值......
'如何遍历枚举'并不是真正的问题,因为我理解这是不可能的,因为类型在运行时不可用,但也许我错过了关于字符串枚举的一些东西?
enum Letter{
A = "A",
B = "B",
E = "E",
I = "I",
}
type Vowl = Letter.A | Letter.E | Letter.I
class LMAP{
test(){}
}
function createLetterMap<T extends Letter>(){
let lmapExtended = new LMAP() as LMAP & {
[key in T]?:string
};
// ?? create default values for keys somehow ??
return lmapExtended;
}
let vowlMap = createLetterMap<Vowl>()
vowlMap[Letter.E] = "Eat" // OK
// vowlMap[Letter.B] = "Bat" // Error! Good!
let defaultVal = vowlMap[Letter.A]; // undefined. Would like it to be populated.
更一般地说,我想使用字符串枚举的联合来生成键控对象,在这些对象中我可以使用枚举作为键来处理类似这样的情况:
fn(v:Vowl){
...
letterMap[v].someVowlReleatedWork()
...
}
我已经探索了替代方案,只是使用~工作~的实际地图,但如果我能正确指定类型,似乎有一种方法可以让事情变得更干净......
我想出的最好的方法是制作一个包含在联合类型中的额外枚举数组,并同时使用联合和工厂数组;类似下面的东西,看起来有点愚蠢:
...
let Vowls = [Letter.A,... ]
createLetterMap<Vowl>(Vowls)
解决方案
您不能将类型定义用作值,因为它们在运行时被删除 -for(let key of keyof Vowl
不起作用。
您可以将地图实现为一个类,或者如果您真的想在运行时提取键,您可以使用自定义转换器,例如ts-transformer-keys。
enum Letter {
A = "A",
B = "B",
E = "E",
I = "I",
}
type Vowl = Letter.A | Letter.E | Letter.I
interface IMapper<T> { operation(value: T): void }
class VowlMapper implements IMapper<Vowl> {
operation(vowel: Vowl) {
console.log("VowlMapper: " + vowel);
}
}
class LetterMap<T extends Letter> {
private map: IMapper<T> & { [key in T]?: string };
constructor(map: IMapper<T>) {
this.map = map;
}
get(letter: T) {
return this.map[letter] ?? letter;
}
set(letter: T, value: any) {
this.map[letter] = value;
}
operation(value: T) {
return this.map.operation(value);
}
}
let vowlMap = new LetterMap(new VowlMapper())
vowlMap.set(Letter.E, "Eat");
// vowlMap.set(Letter.B, "Bat"); // Error! Good!
console.log(vowlMap.get(Letter.A)) // A
//console.log(vowlMap.get(Letter.B)) // error
console.log(vowlMap.get(Letter.E)) // Eat
vowlMap.operation(Letter.A); // VowlMapper: A
查看操场示例。
推荐阅读
- sql - 使用多个 with 优化慢查询
- airflow - 如何在 Airflow 中使用 last_mod_dt(时间戳)从 oracle 数据源中执行每小时增量提取?
- sql - 如何将查询转换为使用联接?
- sql - 行号如 1 - 1.1 1.2 1.3 2 - 2.1 2.2 2.3
- ruby-on-rails - 为什么未初始化常量 Spree::V2::Storefront::Product?
- javascript - Javascript 自动完成从 Id 更改为 Name
- python-3.x - OpenPyXL 不会保存到带有替换更改的新 Excel 文件
- ios - UIView transitionWIthView 简单的改变图像动画——如何明确提及'self'
- python - 在 Python 中使用数值积分的拉普拉斯变换精度很差
- eclipse - 在嵌入式码头 9.4.x 中热部署一个爆炸的 webapp