在TypeScript class Foo {}
中生成名称声明Foo
,它是类Foo
的实例的类型,它生成变量Foo
,它是构造函数Foo
类的函数。 (TypeScript Declaration Spaces。)给定值Foo
(构造函数)可以使用typeof
运算符来获取类的类型(而不是类的实例的类型) 。
要点:
Code Variable Declaration Name Declaration --------------- ---------------------------- ---------------- class Foo {} variable Foo type Foo typeof Foo type of variable Foo
我想知道的是:给定变量Foo
的类型,是否有编译时运算符来获取类型Foo
,类Foo
的实例类型}?
或者,更一般地说,我如何简洁地描述getWhatIWant
的返回类型(下方)?
考虑:
class Base {
constructor(someArgument: string) {}
}
class A extends Base { _brand: 'A' }
class B extends Base { _brand: 'B' }
class C extends Base { _brand: 'C' }
let allOfTheLetters = { A, B, C };
我想要一个带有构造函数名称的对象作为键,并将每个类的实例作为值。文字版本是:
let whatIWouldLike = {
A: new A('same params'),
B: new B('same params'),
C: new C('same params')
}
我试图将allOfTheLetters
转换为whatIWouldLike
。它在JavaScript中没有问题 - 迭代键和值:
function getWhatIWant(letters) {
let result = {};
Object.keys(letters).forEach((key) => result[key] = new letters[key]('same params'));
return result;
}
如何描述此功能的返回类型?映射类型让我接近:
type TypeIWant = {[key in keyof typeof allOfTheLetters ]: typeof allOfTheLetters [key]};
let example: TypeIWant;
let test: 'B' = example.B._brand; // Error: Property '_brand' does not exist on type 'typeof B'
example.A
的类型为'typeof A'
,而不是我需要的'A'
。
如果instanceof
是可以转换类型的编译时运算符,那么我可以将类型'typeof A'
转换为'A'
,并且我得到了我想要的内容。但这不是它的工作原理。
如何在不写出每个键值对的情况下描述getWhatIWant
函数返回的对象类型,就像我创建whatIWouldLike
一样?
答案 0 :(得分:3)
我认为您与映射类型非常接近。让我们来看看你的课程:
class Base {
constructor(someArgument: string) {}
}
class A extends Base { _brand: 'A'; }
class B extends Base { _brand: 'B'; }
class C extends Base { _brand: 'C'; }
let allOfTheLetters = { A, B, C };
好的,所以你的所有类都有一个带有一个string
参数的构造函数。让我们来描述一下:
type BaseConstructor<T> = new (someArgument: string) => T;
现在让我们根据allOfTheLetters
的输出描述getWhatIWant()
的类型。是的,我正在做backwards。如果输出是一个值为实例的对象,则输入是一个对象,其值是那些非常相同的实例的构造函数,按键映射:
type DictionaryOfConstructors<T> = {
[K in keyof T]: BaseConstructor<T[K]>
}
现在我们可以定义getWhatIWant()
的类型:
function getWhatIWant<T>(letters: DictionaryOfConstructors<T>): T {
let result: any = {};
// note I have to assert that `key` is `keyof T` below
Object.keys(letters).forEach((key:keyof T) => result[key] =
new letters[key]('same params'));
return result;
}
let example = getWhatIWant(allOfTheLetters);
let test: 'B' = example.B._brand; // it works!
这是有效的原因是因为给定实例类型(T
变为new(...)=>T
)比描述构造函数类型的实例类型更容易描述构造函数类型(在TypeScript,for now anyway中没有typeof new C(...)
,幸运的是inference from mapped types可以为我们处理向后映射。
希望有所帮助;祝你好运!