Getting type of a property of a typescript class using keyof operator

Is this what you're looking for?

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

and get type of an object property by doing:

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

which is the same as the way of using Pick in typescript, and it can report compile error if there's any invalid key passed in.

Updates

As @astoilkov suggested, a simpler alternative is PropType['key'].


Yes, lookup types work just fine:

type BarType = FooType['bar'];

It expects in this case that FooType is an object like:

type FooType = {
    bar: string;
}

It sets BarType to the same type as FooType['bar'], so to a string.

PS: FooType can also be an interface or class.


Of course, one can get the type of the property by replacing return o[name] into return typeof o[name].

Not really... if you did that:

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

You would get a return value of the type "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function", because you're using the JavaScript typeof operator at runtime, which returns a string like "object", not the compile-time type seen by TypeScript.

TypeScript also uses the keyword typeof as the compile-time type query operator. You can tell the difference by looking at the places where it appears. The type query typeof only appears in places where you are writing a type. For example:

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

In b, you can see that typeof a appears where you would write a type expression, so it is a TypeScript type query, and Array<typeof a> is evaluated as Array<{foo: number}>. On the other hand, in c, typeof a appears where you would write an value expression, so it is the JavaScript typeof operator, and will evaluate to the string "object" at runtime.


As @k0pernikus mentioned, TypeScript doesn't (and doesn't intend to) allow you to get compile-time type information at runtime. So there is no typeof operator which acts at runtime and returns compile-time information.


Of course, if you want type information about a property at compile time, you can do that, using what's called lookup types. Let's examine the return value of that getProperty() function:

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]

That T[K] in a type position means "the type of property with a key of type K on an object of type T". Since this is a type-level operation, you can do it at compile-time without declaring any values of the type T or K. For example,

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

Here, you are looking up the "flags" key of the type of RegExp objects and getting back the string type, and you can declare a value of type RegExp['flags'] without having a value of type RegExp anywhere.


That's the closest I can come to answering your question without more information about what you need. Hope that helps. Good luck!