我想定义一个函数,根据我给出的键返回不同类型的对象。它基本上就像createElement
函数
https://github.com/Microsoft/TypeScript/blob/master/lib/lib.dom.d.ts#L3117
但是,我想使用字符串枚举类型而不是字符串文字。所以我写了这样的东西
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()
}
}
但是,TypeScript似乎不喜欢我将enum Kind
的值放在接口内作为计算属性的方式,它抱怨
A computed property name in an interface must directly refer to a built-in symbol.
问题是,我已经在枚举中定义了常量,我不喜欢使用字符串文字,有没有办法可以使这个有效?这意味着使用Kind枚举值作为KindMap
中的计算属性键。
答案 0 :(得分:1)
有时,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
我尝试使用映射类型实现getAnimal()
,但似乎遇到了错误的推理。但是查阅课程更容易。
内联getAnimalClass
查找也适用于类型推断:
const dog = new kindMap['Dog']();
答案 1 :(得分:1)
原始代码几乎在TypeScript 2.7.2中按原样运行,但它确实有错误,因为可以传入3 Kind
以外的值。
您可以说可以返回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;
}
}
我可能只是直接使用枚举的映射到类构造函数,因为使用它可以很容易地推断出类型:
const kindMap = {
[Kind.Dog]: Dog,
[Kind.Cat]: Cat,
[Kind.Bird]: Bird,
}
const tweeter = new kindMap[Kind.Bird]();
如果希望函数实例化对象,还可以设置并行接口:
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);