使用keyof运算符获取typescript类的属性类型

时间:2017-08-26 10:45:59

标签: typescript

正如关于keyof运算符的Typescript文档中所述,可以使用下面的函数获取对象实例的属性。

function getProperty<T, K extends keyof T>(o: T, name: K) {
    return o[name];
}

当然,可以通过将return o[name]替换为return typeof o[name]来获取属性的类型。有没有办法检索属性的类型而不传递任何对象实例

function getPropertyType<T>(name: keyof T) {
    // something like T[name]?
}

3 个答案:

答案 0 :(得分:8)

  

当然,可以通过将return o[name]替换为return typeof o[name]来获取属性的类型。

不是......如果你这样做了:

function getTypeofProperty<T, K extends keyof T>(o: T, name: K) {
    return typeof o[name];
}

您将获得"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"类型的返回值,因为您在运行时使用JavaScript typeof operator,它返回类似"object"的字符串,而不是TypeScript看到的编译时类型。

TypeScript还使用关键字typeof作为编译时type query operator。您可以通过查看它出现的位置来区分它们。类型查询typeof仅出现在您正在编写类型的位置。例如:

const a = { foo: 0 };
const b: Array<typeof a> = [{ foo: 1 }, { foo: 2 }, {foo: 3}]; 
const c: string = typeof a; // "object"

b中,您可以看到typeof a出现在您要编写类型表达式的位置,因此它是TypeScript类型查询,Array<typeof a>被评估为Array<{foo: number}> 。另一方面,在c中,typeof a会出现在您编写值表达式的位置,因此它是JavaScript typeof运算符,并将在以下位置计算字符串"object"运行时。

正如@ k0pernikus所提到的,TypeScript不允许(并且不打算)允许您在运行时获取编译时类型信息。因此没有typeof运算符在运行时运行并返回编译时信息。

当然,如果您想在编译时获取有关属性的类型信息,那么可以使用所谓的lookup types来执行此操作。让我们检查getProperty()函数的返回值:

function getProperty<T, K extends keyof T>(o: T, name: K) {
    return  o[name];
} // hover over getProperty to see that the return value is of type T[K]

类型位置中的T[K]表示“类型为K的对象上具有类型T的键的属性类型”。由于这是类型级操作,因此您可以在编译时执行此操作,而无需声明类型TK的任何值。例如,

type RegExpFlags = RegExp['flags']; // RegExpFlags is string
const flags: RegExpFlags = 'ig';

在这里,您正在查找"flags"对象类型的RegExp键并返回string类型,并且您可以声明类型为RegExp['flags']的值在任何地方都没有RegExp类型的值。

这是我能够在没有您需要的更多信息的情况下回答您的问题。希望有所帮助。祝你好运!

答案 1 :(得分:2)

这是您要找的吗?

type PropType<TObj, TProp extends keyof TObj> = TObj[TProp];

并通过执行以下操作获取对象属性的类型:

type MyPropType = PropType<ObjType, '<key>'>;

与在打字稿中使用Pick的方式相同,如果传入了任何无效的key,它可以报告编译错误。

答案 2 :(得分:2)

是的,lookup types应该可以正常工作。喜欢:

type FooType = { // interfaces or classes of course also possible
    bar: string;
}

type BarType = FooType['bar']; // BarType is a string now