keyof Type Operator

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

Professional TypeScript Masterclass Lessons

1.Introduction
free
⏱️ 1:54
2.Setup
free
⏱️ 5:44
3.Primitive Types
free
⏱️ 1:42
4.Instance Types
free
⏱️ 1:52
5.Arrays And Tuples
free
⏱️ 1:38
6.Objects
free
⏱️ 1:33
7.const declarations
free
⏱️ 1:03
8.Function Types
free
⏱️ 1:57
9.Structural Typing
free
⏱️ 2:10
10.Classes in TypeScript
free
⏱️ 1:48
11.Target Compiler Option
free
⏱️ 2:37
12.Generics
⏱️ 3:02
13.Special Types any And unknown
⏱️ 2:00
14.JavaScript to TypeScript
⏱️ 1:32
15.Frontend Projects
⏱️ 3:49
16.Type Assertions
⏱️ 2:15
17.Type Casting
⏱️ 1:16
18.Modules
⏱️ 1:55
19.Type Declarations
⏱️ 4:25
20.Creating NPM packages
⏱️ 3:20
21.Async Await
⏱️ 3:05
22.Running in NodeJS
⏱️ 1:40
23.Lexical this
⏱️ 2:34
24.readonly Modifier
⏱️ 1:59
25.Union Types
⏱️ 2:57
26.Literal Types
⏱️ 2:58
27.Type Narrowing
⏱️ 4:19
28.Discriminated Unions
⏱️ 3:29
29.Class Parameter Properties
⏱️ 1:02
30.Strict Compiler Option
⏱️ 6:18
31.null vs undefined
⏱️ 4:19
32.Intersection Types
⏱️ 2:03
33.Optional Modifier
⏱️ 2:47
34.Non Null Assertion Operator
⏱️ 3:40
35.Interfaces
⏱️ 2:28
36.Interface Declaration Merging
⏱️ 1:01
37.Types vs Interfaces
⏱️ 2:16
38.never Type
⏱️ 3:00
39.implements Keyword
⏱️ 1:25
40.Definite Assignment Assertion
⏱️ 2:31
41.User Defined Type Guards
⏱️ 2:02
42.Assertion Functions
⏱️ 3:42
43.Function Overloading
⏱️ 4:15
44.Call Signatures
⏱️ 2:53
45.Abstract Classes
⏱️ 1:53
46.Index Signatures
⏱️ 3:08
47.Readonly Arrays and Tuples
⏱️ 2:58
48.Double Assertions
⏱️ 2:20
49.const Assertions
⏱️ 3:55
50.this Parameter
⏱️ 2:33
51.Generic Constraints
⏱️ 2:43
52.typeof Type Operator
⏱️ 2:12
53.Lookup Types
⏱️ 3:12
54.keyof Type Operator
⏱️ 3:55
55.Conditional Types
⏱️ 4:39
56.Contitional Types with Unions and never
⏱️ 3:32
57.infer Keyword and `ReturnType<T>`
⏱️ 3:47
58.Mapped Types
⏱️ 2:48
59.Mapped Type Modifiers
⏱️ 3:37
60.Template Literal Type
⏱️ 4:28
61.Partial<T>
⏱️ 1:27
62.Required<T>
⏱️ 1:36
63.Readonly<T>
⏱️ 1:34
64.Record<K, T>
⏱️ 4:05
65.Project References
⏱️ 4:18
66.undefined vs. optional
⏱️ 2:48
67.satisfies Operator
⏱️ 2:42
68.PropertyKey Type
⏱️ 0:57
69.ThisType<T>
⏱️ 4:11
70.Awaited<T>
⏱️ 4:12
71.String Manipulation Types
⏱️ 3:36
72.Mapped Types as Clauses
⏱️ 4:01
73.Union vs Intersection Mental Model
⏱️ 3:36
74.Enums are Bad
⏱️ 8:11

keyof Type Operator

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

Syntax

Creates a type which is a union of the keys present in the provided type e.g.:

type Person = {
name: string,
age: number,
location: string,
};

type PersonKeys = keyof Person; // 'name' | 'age' | 'location'

Ensuring Valid Keys

Example use case:

type Person = {
name: string,
age: number,
location: string,
};

const john: Person = {
name: 'John',
age: 35,
location: 'Melbourne',
};

function logGet(obj: Person, key: keyof Person) {
const value = obj[key];
console.log('Getting:', key, value);
return value;
}

const age = logGet(john, 'age'); // 35
const email = logGet(john, 'email')); // Compiletime Error: invalid value `email`

Combining with Generic Constraints

You can combine with generic constraints (something we looked at in a previous lesson) to create pretty powerful functions e.g.:

function logGet<Obj, Key extends keyof Obj>(obj: Obj, key: Key) {
const value = obj[key];
console.log('Getting:', key, value);
return value;
}
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

Here we have a type representing a person with member's name and location of type string and age of type number. We have an example of such a person in the form of John age 35 living in Melbourne. We have a utility function that lets us access any member of John along with logging out a statement to the console. As an example, we can use this method to get John's age. Now an issue with the signature of our log function is that it allows any old string key to be passed in. For example, we can pass in a key

00:33

that is not present on the John object like email. Now we can improve the situation by replacing our open-ended string with a limited set of string literals using a string literal union, for example, we can say that key must be name, age, or location, which are the only valid keys for the person type. And now type strip correctly highlights invalid access as an error. However, this list of keys is essentially code duplication that will have to be maintained as we continue to work on the person type.

01:05

Fortunately, this is something that can be automated with the TypeScript key of type operator. The key of type operator takes a type as input and returns a union of the keys from that type. And this is exactly the union of the strings that we wanted. So we can replace our hand coded union of string littles with a simple key of query on the person type. And because we are restricting the keys to be from the person type, we'll annotate the obs to be of type person as well. Now notice that our log GA function doesn't have any code specific to the person type

01:39

to make this function more general. We can use generics using a generic type for the ops and a generic type for the key. And now the requirement that key must be something that is in the key of obs can be enforced by a generic constraint when we define the generic argument. Now with this generic constraint, TypeScript knows that key will be something that is in the key of orbit. So when we try to index OB with key in our JavaScript code, TypeScript correctly infers the type of the return value to be an index lookup type OB key.

02:13

And since value is what we return from the log function, the return type of the function is also inferred to be the lookup type OB key. Now with this function signature in place when obs is of type person and key is of type age, the return type will be the lookup person age and we can see that it needs to be a number. And indeed that is what is automatically inferred when we try to use log to get Jones age. And now we can get rid of the invalid access for the email property.

02:46

Now, similar to how we have the log function, we can easily apply the same knowledge to build a log set function. The body of the function is pretty simple in terms of the function's signature. It is very similar To the signature of the log get function. The only difference is that the log set function takes an additional third argument, which has been annotated with a lookup type object key. And we've seen this type before as well. This is exactly the return type of the log get function. And now we get a nice utility function that can be used to set any value on a member of any type.

03:20

And if you make any city mistakes, for example, misspell a property or provide an invalid type for that particular property, we get a nice compiler error from TypeScript. Now the key of operator by itself is quite simple. It simply returns the union of strings of keys of any given type. Here we've combined the key of operator with other features in TypeScript, which are generics, generic constraints, as well as with lookup types to provide type safety for something that can be used to observe any given object.

Professional TypeScript Masterclass

Professional TypeScript Masterclass

1.Introduction
free
⏱️ 1:54
2.Setup
free
⏱️ 5:44
3.Primitive Types
free
⏱️ 1:42
4.Instance Types
free
⏱️ 1:52
5.Arrays And Tuples
free
⏱️ 1:38
6.Objects
free
⏱️ 1:33
7.const declarations
free
⏱️ 1:03
8.Function Types
free
⏱️ 1:57
9.Structural Typing
free
⏱️ 2:10
10.Classes in TypeScript
free
⏱️ 1:48
11.Target Compiler Option
free
⏱️ 2:37
12.Generics
⏱️ 3:02
13.Special Types any And unknown
⏱️ 2:00
14.JavaScript to TypeScript
⏱️ 1:32
15.Frontend Projects
⏱️ 3:49
16.Type Assertions
⏱️ 2:15
17.Type Casting
⏱️ 1:16
18.Modules
⏱️ 1:55
19.Type Declarations
⏱️ 4:25
20.Creating NPM packages
⏱️ 3:20
21.Async Await
⏱️ 3:05
22.Running in NodeJS
⏱️ 1:40
23.Lexical this
⏱️ 2:34
24.readonly Modifier
⏱️ 1:59
25.Union Types
⏱️ 2:57
26.Literal Types
⏱️ 2:58
27.Type Narrowing
⏱️ 4:19
28.Discriminated Unions
⏱️ 3:29
29.Class Parameter Properties
⏱️ 1:02
30.Strict Compiler Option
⏱️ 6:18
31.null vs undefined
⏱️ 4:19
32.Intersection Types
⏱️ 2:03
33.Optional Modifier
⏱️ 2:47
34.Non Null Assertion Operator
⏱️ 3:40
35.Interfaces
⏱️ 2:28
36.Interface Declaration Merging
⏱️ 1:01
37.Types vs Interfaces
⏱️ 2:16
38.never Type
⏱️ 3:00
39.implements Keyword
⏱️ 1:25
40.Definite Assignment Assertion
⏱️ 2:31
41.User Defined Type Guards
⏱️ 2:02
42.Assertion Functions
⏱️ 3:42
43.Function Overloading
⏱️ 4:15
44.Call Signatures
⏱️ 2:53
45.Abstract Classes
⏱️ 1:53
46.Index Signatures
⏱️ 3:08
47.Readonly Arrays and Tuples
⏱️ 2:58
48.Double Assertions
⏱️ 2:20
49.const Assertions
⏱️ 3:55
50.this Parameter
⏱️ 2:33
51.Generic Constraints
⏱️ 2:43
52.typeof Type Operator
⏱️ 2:12
53.Lookup Types
⏱️ 3:12
54.keyof Type Operator
⏱️ 3:55
55.Conditional Types
⏱️ 4:39
56.Contitional Types with Unions and never
⏱️ 3:32
57.infer Keyword and `ReturnType<T>`
⏱️ 3:47
58.Mapped Types
⏱️ 2:48
59.Mapped Type Modifiers
⏱️ 3:37
60.Template Literal Type
⏱️ 4:28
61.Partial<T>
⏱️ 1:27
62.Required<T>
⏱️ 1:36
63.Readonly<T>
⏱️ 1:34
64.Record<K, T>
⏱️ 4:05
65.Project References
⏱️ 4:18
66.undefined vs. optional
⏱️ 2:48
67.satisfies Operator
⏱️ 2:42
68.PropertyKey Type
⏱️ 0:57
69.ThisType<T>
⏱️ 4:11
70.Awaited<T>
⏱️ 4:12
71.String Manipulation Types
⏱️ 3:36
72.Mapped Types as Clauses
⏱️ 4:01
73.Union vs Intersection Mental Model
⏱️ 3:36
74.Enums are Bad
⏱️ 8:11