[英]Use string enum value in TypeScript interface as a computed property key
I want to define a function returns different type of object based on the key I give.我想定义一个函数,根据我给出的键返回不同类型的对象。 It's basically like the trick used here in
createElement
function它基本上就像在
createElement
函数中使用的技巧
https://github.com/Microsoft/TypeScript/blob/master/lib/lib.dom.d.ts#L3117 https://github.com/Microsoft/TypeScript/blob/master/lib/lib.dom.d.ts#L3117
However, instead of string literal, I want to use string enum type instead.但是,我想使用字符串枚举类型而不是字符串文字。 So I wrote something like this
所以我写了这样的东西
class Dog {}
class Cat {}
class Bird {}
enum Kind {
Dog = 'Dog',
Cat = 'Cat',
Bird = 'Bird'
}
interface KindMap {
[Kind.Dog]: Dog
[Kind.Cat]: Cat
[Kind.Bird]: Bird
}
function getAnimal<K extends keyof KindMap> (key: K): KindMap[K] {
switch (key) {
case Kind.Dog:
return new Dog()
case Kind.Cat:
return new Cat()
case Kind.Bird:
return new Bird()
}
}
However, TypeScript seems doesn't like the way I put the enum Kind
's value inside interface as the computed property, it complains但是,TypeScript 似乎不喜欢我将
enum Kind
的值作为计算属性放在 interface 中的方式,它抱怨
A computed property name in an interface must directly refer to a built-in symbol.
Here comes the question, I already have the constants defined in the enum, I don't like to use string literal, is there a way I can make this works?问题来了,我已经在枚举中定义了常量,我不喜欢使用字符串文字,有什么办法可以使它起作用吗? Which means use the Kind enum's value as the computed property key in the
KindMap
.这意味着使用 Kind 枚举的值作为
KindMap
的计算属性键。
Sometimes a simple object with keyof
is simpler than an enum in TypeScript:有时,带有
keyof
的简单对象比 TypeScript 中的枚举更简单:
class Dog { }
class Cat { }
const kindMap = {
Dog,
Cat
};
type KindMap = typeof kindMap;
function getAnimalClass<K extends keyof KindMap>(key: K): KindMap[K] {
return kindMap[key];
}
// These types are inferred correctly
const DogClass = getAnimalClass('Dog');
const dog = new DogClass();
const CatClass = getAnimalClass('Cat');
const cat = new CatClass();
Try it in TypeScript Playground 在 TypeScript Playground 中尝试
I tried to implement getAnimal()
with mapped types but seemed to run into buggy inference.我尝试使用映射类型实现
getAnimal()
但似乎遇到了错误的推理。 But looking up the class was easier.但是查找类更容易。
Inlining the getAnimalClass
lookup also works with type inference:内联
getAnimalClass
查找也适用于类型推断:
const dog = new kindMap['Dog']();
The original code almost works as-is in TypeScript 2.7.2, although it does have an error because values other than the 3 Kind
s may be passed in.原始代码几乎按原样在 TypeScript 2.7.2 中工作,尽管它确实有错误,因为可能会传入 3
Kind
以外的值。
You can say that it's possible to return undefined
:你可以说有可能返回
undefined
:
function getAnimal<K extends keyof KindMap>(key: K): undefined | KindMap[K] {
switch (key) {
case Kind.Dog:
return new Dog()
case Kind.Cat:
return new Cat()
case Kind.Bird:
return new Bird()
default:
return undefined;
}
}
I'd probably just use a map of the enum to the class constructor directly, as using it can easily infer the type:我可能只是直接使用枚举到类构造函数的映射,因为使用它可以轻松推断类型:
const kindMap = {
[Kind.Dog]: Dog,
[Kind.Cat]: Cat,
[Kind.Bird]: Bird,
}
const tweeter = new kindMap[Kind.Bird]();
If you want the function to instantiate the objects, you can also set up a parallel interface:如果你想让函数实例化对象,你也可以设置一个并行接口:
interface KindMap {
[Kind.Dog]: Dog,
[Kind.Cat]: Cat,
[Kind.Bird]: Bird,
}
const getAnimal = <K extends Kind>(k: K): KindMap[K] => new kindMap[k]();
const meower = getAnimal(Kind.Cat);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.