Ensuring the correct type of keys during Object.entries iteration in TypeScript

When using Object.entries(), it returns the correct value types, but the keys are of type string[], which is incorrect. I want TypeScript to recognize my keys correctly. I attempted to use as const on the object, but it did not have any effect.

Is there a way to assert the type in this scenario?

const demo = {
  a: 'TEST',
  b: 222,
} as const

Object.entries(demo)
  .forEach(([key, value]) => { // key is string and not "a" | "b"
    console.log([key, value])
  })

// reproduce same types as above
Object.entries(demo)
  .forEach(([key, value]: [string, typeof demo[keyof typeof demo]]) => {
    console.log([key, value])
  })

// now trying to change string to actual keys, error :(
Object.entries(demo)
  .forEach(([key, value]: [keyof typeof demo, typeof demo[keyof typeof demo]]) => {
    console.log([key, value])
  })

// so instead trying to force somehow type assertion
Object.entries(demo)
  .forEach(([key as keyof typeof demo, value]) => { // how to make assertion???
    console.log([key, value])
  })

Playground

Answer №1

It's important to note that keys are represented as string[], which may seem unusual but serves a specific purpose.

The design choice was deliberate in order to allow for object extension. While you might be certain that the object won't be extended, the type system cannot guarantee this. Here's an example:

interface Person {
  name: string;
  age: number;
}

interface Employee extends Person {
  department: string;
}

const someFunction (person: Person) {
  Object.entries([key, value] => {
    // The 'key' here can vary and may not always be 'name' or 'age'. 
    // For instance, it could be 'department' or any other string value.
  });
}

const alice: Person = { name: 'alice', age: 30 }
const bob: Employee = { name: 'bob', age: 30, department: 'legal' }

someFunction(alice); // This is valid
someFunction(bob); // This is also valid

If you want to assert that there are no additional properties, you can use the following method:

Object.entries(demo)
  .forEach(([k, value]) => {
    const key = k as keyof typeof demo
    console.log([key, value])
  })

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

The module is missing a declaration file and therefore has an implicit type of 'any'. This error (TS7016) occurs in TypeScript version 2.0

So I've been experimenting with the module react-image-gallery. Surprisingly, there seems to be no types available for this package when trying to install it using npm. When attempting npm install @types/react-image-gallery, all I get is a 404 error. ...

The parameters 'event' and 'payload' do not match in type

Upon running the build command, I encountered a type error that states: Type error: Type '(event: React.FormEvent) => void' is not assignable to type 'FormSubmitHandler'. Types of parameters 'event' and 'payload&apos ...

Steps for aligning the upper rectangular text in the center of the larger rectangular border

https://i.stack.imgur.com/7yr5V.png I was aware of a particular element in html that had text positioned in the upper left corner, but my knowledge didn't go beyond that. Should I be adjusting the translation on both the X and Y axes based on the par ...

How to disable click event binding in Angular2 after it has been clicked once

Within my application, there is a button that has a click event attached to it: <button class="btn btn-default" (click)="doSomething()"> I am wondering if there is a way to remove the (click) event from the button within the doSomething method so t ...

Guide on incorporating external .d.ts files for a module

I'm currently delving into the process of utilizing an external .d.ts file that is not included in the module. My intention is to make use of xlsx, which lacks its own type definitions, and instead incorporate them from the package @types/xlsx. Afte ...

What is the best way to retrieve the post JSON data in the event of a 404 error?

When my service call returns a 404 error, I want to display the server's message indicating the status. The response includes a status code and message in JSON format for success or failure. This is an example of my current service call: this._trans ...

What is the best way to handle asynchronous actions while initializing a database in Next.js?

My goal is to create tables during the database initialization stage with a structure like this: CREATE TABLE IF NOT EXISTS users ( "id" SERIAL PRIMARY KEY, "created_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "name&quo ...

Is there a way to track all Angular form controls that have switched between being enabled and disabled?

Summary: When a FormGroup contains a nested FormControl that changes from disabled to enabled or vice versa, the FormGroup is not marked as dirty. Details: How can you identify all form controls within a FormGroup that have switched between being enabled ...

Using create-react-app with TypeScript for server-side rendering

My current project is built with create-react-app using typescript (tsx files). I'm now interested in implementing SSR for the project, but I'm not exactly sure where to begin. In the past, I've successfully implemented SSR with typescript ...

Error retrieving the latest token in Angular before the component has fully loaded

I am seeking relevant advice to address my specific need: In my Angular application, I have implemented a jwt-based authentication system. After obtaining a new token and refresh token, I have set up a setTimeout function to ensure the token is refreshed ...

Limit the category to a specific subset of strings

Looking for a way to implement literal type restrictions without using type aliases: const foo = (a: 'string', b: 'string') => { } foo("123", "abc") // should fail foo("123" as 'string', "abc" as 'string') I pr ...

Eslint highlighting the initial function declaration within a Vue script

I'm currently creating a Vue file using a Typescript script, and encountering an unusual Eslint "error." https://i.sstatic.net/UXv3A.png The issue arises on line 15 with this specific complaint: Parsing error: Unexpected token, expected "," Interes ...

Tips for removing the Y-Axis entirely from a CanavasJS chart

I'm working with a canvasJS chart and my goal is to completely hide the Y-Axis. I've managed to remove the Y-Axis line and title in this JSFiddle example. I came across these properties to hide the Y-Axis title and line, but I'm struggling t ...

Implementing the "$store" property within Vue components

Click here for a guide on how to type the $store property. Unfortunately, I've been encountering issues with it. In my Vue 2 project created using vue-cliI, I included a vuex.d.ts file in ./src directory but the $store property in my components still ...

Error: Unable to modify a property that is marked as read-only on object '#<Object>' in Redux Toolkit slice for Firebase Storage in React Native

Hey there! I've been working on setting my downloadUrl after uploading to firebase storage using Redux Toolkit, but I'm facing some challenges. While I have a workaround, I'd prefer to do it the right way. Unfortunately, I can't seem to ...

Change the value of the checked property to modify the checked status

This is a miniCalculator project. In this mini calculator, I am trying to calculate the operation when the "calculate" button is pressed. However, in order for the calculations to run correctly in the operations.component.ts file, I need to toggle the val ...

Encountering a TS1005 error while trying to import types from a type definition file

Within my project, one of the libraries called parse5 is providing typing information in .d.ts files. The current syntax used to import types is causing several TypeScript errors during application runtime because TypeScript does not seem to recognize this ...

How can I add a JavaScript-created element into a Primeng TurboTable component?

I am in the process of replacing a custom-made table with PrimeNG's turbotable. The issue I'm facing is that when I try to insert buttons into the table that call specific JavaScript functions, they end up displaying as [object HTMLInputElement] ...

Step-by-step guide on how to index timestamp type using Knex.js

I'm in the process of indexing the created_at and updated_at columns using knex js. However, when I try to use the index() function, I encounter the following error: Property 'index' does not exist on type 'void' await knex.sche ...

TS2322 error: What does it mean when the type is both not assignable and assignable?

I've been delving into the world of generics with Java and C#, but TypeScript is throwing me for a loop. Can someone shed some light on this confusion? constructor FooAdapter(): FooAdapter Type 'FooAdapter' is not assignable to type 'A ...