What made the "in" operator not the best choice in this situation?

When I set out to create a type that represents the values of a given object type, I initially came up 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> ; 

However, it turns out that using in here is unnecessary. I could have simply used T[keyof T].

I've noticed the use of the in operator in similar scenarios like this one:

type OptionsFlags<Type> = {
  [Property in keyof Type]: boolean;
};

Why wasn't it necessary in my situation? What key concept did I overlook regarding the usage of in? When should I consider using in as a rule of thumb?

Answer №1

in is used in your example for Mapped types.

What you need is :

type ValueOf<T extends {}> = T[keyof T] 

type foo =  ValueOf<Book> ; // string | number

Test it out


A Mapped type is a kind of generic type that uses a union of PropertyKeys (often created using keyof) to loop through keys and create a type. It typically looks like :

{ [Property in keyof Type]: whatEverType; }

Answer №2

Understanding Mapped types in Typescript

Utilizing the in keyword when working with mapped types is crucial, as demonstrated in the following example:

type OptionsFlags<Type> = {
  [Property in keyof Type]: boolean;
};

Mapped types allow you to construct a new object type by iterating through existing properties:

keyof Book = 'name' | 'year' | 'author'
OptionsFlags<Book> = {
  name: boolean;
  year: boolean;
  author: boolean;
}

Exploring Indexed Access Types in Typescript

An important aspect of indexed access types like your ValueOf type is eliminating the use of k in:

type ValueOf<T extends {}> = T[keyof T];

Indexed access types enable you to retrieve the type associated with a specific key within an object:

type BookName = Book['name'] // string

Additonally, the key can be a union type, exemplified by keyof T.

Consider it as "What types do I obtain when cycling through all these key values?" (a form of projection). For instance, using your Book type would result in this sequence:

ValueOf<Book>
=> Book[keyof Book]
=> Book['name' | 'year' | 'author']
=> Book['name'] | Book['year'] | Book['author']
=> string | number | string
=> string | number

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What are the best practices for preventing risky assignments between Ref<string> and Ref<string | undefined>?

Is there a way in Typescript to prevent assigning a Ref<string> to Ref<string | undefined> when using Vue's ref function to create typed Ref objects? Example When trying to assign undefined to a Ref<string>, an error is expected: co ...

An issue has occurred with attempting to access the 'phone' property of a null value. This error is at the root of the problem and needs to

I have implemented a function to retrieve all clients from an API: this.ws.getallclients().subscribe( client => { this.client = client.map((clients) => { this.filteredOptions = this.addsale.controls['client_id'].valueChanges. ...

Tips for managing various potential return types in TypeScript?

In my research on the topic, I came across a discussion thread about obtaining the local IP address in Node.js at Get local IP address in Node.js. In that thread, there is a code snippet that I would like to incorporate: import net from 'net'; c ...

Redirect user to the "Confirm Logout" page in Keycloak after refreshing the page before logging out

While working on a project with keycloak, I've encountered an issue that I can't seem to figure out. After logging in and navigating to my project's page, everything operates smoothly. However, if I happen to refresh the page before logging ...

In Angular/Typescript, dynamically add a class to a `td` element when it is clicked. Toggle the class on and off

My problem arises when trying to individually control the arrow icons for each column in my COVID-19 data table. By using Angular methods, I aim to show ascending and descending arrows upon sorting but run into the challenge of changing arrows across all c ...

The Aurelia application encounters a "Maximum call stack size exceeded" error while trying to bind FullCalendar

I am currently working on setting up a JQuery plugin (FullCalendar) within my Aurelia application, which is built using TypeScript. I am relatively new to web development and just trying to get a basic example up and running. To start off, I utilized this ...

What is the best way to iterate through all class properties that are specified using class-validator?

I have a class defined using the class-validator package. class Shape { @IsString() value?: string @IsString() id?: string } I am trying to find a way to retrieve the properties and types specified in this class. Is there a method to do s ...

Error TS2604: Upon importing the 'material-ui' button from one package into another

Our team is in the process of implementing a new front-end for our application by transitioning from standard react to typescript. As someone who is relatively new to development, I have been struggling with a particular issue for several days now. The set ...

A guide on capturing the response in the POST method within Angular 7

I'm currently working with Angular 7 and I need a way to know if the data has been successfully saved or not. Within my web service code, I have designated "Success" as the status when data is saved correctly, and "Unsuccessful" if the data is not sa ...

What is the best way to link labels with input fields located separately in Angular?

Imagine a scenario where labels and form fields are being created in a *ngFor loop, as shown below: app.component.ts export class AppComponent { items = ['aaa', 'bbbbbb', 'ccccccccc'] } app.component.html <div class ...

Error TS2322: Cannot assign type 'Promise<Hero | undefined>' to type 'Promise<Hero>'

I am currently studying angular4 using the angular tutorial. Here is a function to retrieve a hero from a service: @Injectable() export class HeroService { getHeroes(): Promise<Hero[]> { return new Promise(resolve => { // ...

Can you clarify the significance of the "1" in this particular Typescript code snippet?

Can anyone provide some insight into the purpose of this '1' in the following TS code snippet? decryptPassPhrase() { this.$encrypt.setPrivateKey(privateKey); this.decryptedPassPhrase = this.$encrypt.decrypt(this.encryptedPassPhrase); ...

Is there a way to specify a type for a CSS color in TypeScript?

Consider this code snippet: type Color = string; interface Props { color: Color; text: string; } function Badge(props: Props) { return `<div style="color:${props.color}">${props.text}</div>`; } var badge = Badge({ color: &ap ...

Tips for avoiding a React component from causing the page to freeze post-loading

Currently, I am utilizing the uiwjs/react-json-view library to display JSON data. However, there seems to be an issue when attempting to load a large JSON file as it causes the page to freeze. To address this problem, I have already implemented Suspense an ...

Isolated Modules in Angular Version 17 and Beyond

Having worked with an earlier version of Angular, I am facing issues with my navbar routes not working properly on my Contact Page. Can someone shed some light on this for me? If you want to take a look at the code, here is the link: https://github.com/Lo ...

Checkboxes within Angular's reactive forms are a powerful tool for creating dynamic user

Currently, I am working on a contact form that includes checkboxes for users to select multiple options, with the requirement of selecting at least one box. My challenge lies in figuring out how to pass all the selected checkboxes' data to an API usin ...

The VSCode's intellisense for Angular Material fails to function effectively

In the midst of my project on Angular version 13, I have successfully installed Angular Material using the command below: ng add @angular/material The package has been properly included in the node_modules folder. However, when working with TypeScript ...

Angular 13: Masking User Input with Reactive Form Controls

Looking to incorporate a phone number input field with formatting in a reactive form. The desired format is (123) 456-7890. For reference, check out this example link: https://stackblitz.com/edit/angular13-reactive-form-validation-y1qwmf?file=src/app/app. ...

Creating an interceptor to customize default repository methods in loopback4

Whenever I attempt to access the default repository code, I need to manipulate certain values before triggering the default crud function in the repository. How can I accomplish this? For example: ... @repository.getter('PersonRepository') priva ...

Trouble with Jest when trying to use route alias in Next.js with Typescript

Currently, I am developing a Next.js App (v13.2.3) using Typescript and have set up a path alias in the tsconfig.json. Does anyone know how I can configure the jest environment to recognize this path alias? // tsconfig.json { "compilerOptions": ...