In attempt to make type which should be values of given object type I started with this:
type Book = {
name:string,
year:number,
author:string
}
// expected result "string" | "number"
type ValueOf<T extends {}> = T[k in keyof T] // error due to "in"
let x:ValueOf<Book> ;
But seems in
is redundant here. I could just have used T[keyof T]
.
While I have seen in
operator in similar cases like this:
type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};
Why wasn't it needed in my case? What concept did I miss related to in
usage? What is rule of thumb when I could use in
?
CodePudding user response:
in
in your example is for Mapped types.
What you want is :
type ValueOf<T extends {}> = T[keyof T]
type foo = ValueOf<Book> ; // string | number
A Mapped type is a generic type which uses a union of PropertyKeys (frequently created via a keyof) to iterate through keys to create a type. I mostly look like :
{ [Property in keyof Type]: whatEverType; }
CodePudding user response:
Mapped types
in
should be used in mapped types such as the last type in your question:
type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};
In mapped types, you are building a new object
type through iteration:
keyof Book = 'name' | 'year' | 'author'
OptionsFlags<Book> = {
name: boolean;
year: boolean;
author: boolean;
}
Indexed Access Types
Your ValueOf
type is an indexed access type so you should remove the k in
:
type ValueOf<T extends {}> = T[keyof T];
In an indexed access type you are accessing the type of the value for the key you pass between angle brackets:
type BookName = Book['name'] // string
But the key can also be an union type, which is the case of keyof T
.
You may read this as "What types do I get when I go through all these key values?" (that would be a kind of projection in my mind). And with your Book
type, Typescript would go through all these steps:
ValueOf<Book>
=> Book[keyof Book]
=> Book['name' | 'year' | 'author']
=> Book['name'] | Book['year'] | Book['author']
=> string | number | string
=> string | number