Looking for a TypeScript annotation that allows accessing an object property using a variable

When working with plain JavaScript, we have the ability to access an object's property value using a variable.

For example, this is permitted:

let obj = { a: 100, b: 'Need help with TypeScript', c: new Date() };
let prop = 'b';
console.log( obj[prop] );  // Need help with TypeScript

However, when introducing TypeScript and declaring prop as a string, it may lead to an index error as shown below.

let obj: object = { a: 100, b: 'Need help with TypeScript', c: new Date() };
let prop: string = 'b';
console.log( obj[prop] );  // TypeScript error element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.

What would be the correct way to annotate the code above?

Edit Dec. 9, 2019: When initially posting the question, I assumed there would be a general solution that isn't solely reliant on my specific object example.

In my scenario, I have a function that takes a property name as an argument. This function is responsible for sorting an array based on the provided property name. The original JavaScript code I'm migrating to TypeScript is capable of sorting any array of objects.

Answer №1

It is advised to avoid using object as a type in TypeScript, as it can lead to ambiguity.

Instead, consider defining a specific type that clearly specifies the structure of your data:

let obj: { [key: string]: number } = { a: 100, b: 200, c: 300 };
let prop: string = 'b';
console.log(obj[prop]);

To further refine your type definition, you can utilize the [key in type] syntax with a custom type:

type props = 'a' | 'b' | 'c';
let obj: { [key in props]: number } = { a: 100, b: 200, c: 300 };
let prop: props = 'b';
console.log(obj[prop]);

For a more advanced approach, you can utilize interfaces for better organization and access using the keyof operator:

interface IProps{
  a: number,
  b: number,
  c: number
}
let obj: { [key in keyof IProps]: number} = { a: 100, b: 200, c: 300 };
let prop: keyof IProps = 'b';
console.log(obj[prop]);

This last example serves as a demonstration and reference rather than a definitive solution to the initial issue raised by the OP.

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

Visual Studio - TypeScript project synchronization issue

Currently using the 2015 version of Visual Studio Community, I am facing an issue while working on a typescript project. Whenever I make modifications to the code, debug it, and save it using ctrl + s followed by refreshing the browser with ctrl + r, the c ...

Theme not being rendered properly following the generation of a dynamic component in Angular

I am currently working on an Angular 9 application and I have successfully implemented a print functionality by creating components dynamically. However, I have encountered an issue where the CSS properties defined in the print-report.component.scss file a ...

TypeScript application was constructed with incorrect imports from the src folder instead of the dist folder

Summary: App successfully built but importing files from src folder instead of dist I have a TypeScript-powered Express application. This is the configuration of tsconfig.json file: { "compilerOptions": { "target": "es5&quo ...

Handlebar files are not compatible with Typescript loading capabilities

I am encountering an issue with my directory structure as follows : src |- server |- myServer.ts |- views |- myView.hbs dist |- server |- myServer.js The problem lies in the fact that the dist folder does not have a views subfolder, where the J ...

Utilizing Typescript's baseUrl compiler configuration for node development

Is there a way for node's module loader to support TS's baseUrl compiler option? With the introduction of the baseUrl compiler option in TS 2, project relative require() and import requests are now possible. However, this feature requires that ...

What is the best way to set up a property in a service that will be used by multiple components?

Here is an example of how my service is structured: export class UserService { constructor() {} coords: Coordinates; getPosition() { navigator.geolocation.getCurrentPosition(position => { this.coords = [position.coords.latitude, posit ...

It is feasible to completely override a class in TypeScript

I have a subclass defined as follows: customException.ts /** * Custom Error class. * * @class Error * @extends {Error} */ class Error { /** * @type {string} * @memberof Error */ message: string; /** * @type {boolean} * @memberof ...

ERROR TS1086: A declaration of an accessor within an ambient context is not allowed. Accessor for firebaseUiConfig(): NativeFirebaseUIAuthConfig

Trying to create a Single Page Application with Angular/CLI 8. Everything was running smoothly locally until I tried to add Firebase authentication to the app. Upon compiling through Visual Studio Code, I encountered the following error message: ERROR in ...

Incorporate an HTML span element with an onclick function bound in Angular framework

Is there a way to incorporate different icons by adding a span based on a flag, with an onclick event that triggers an internal function defined in the component ts? testfunc(){ console.log("it works") } flagToIcon(flag: boolean) { switch ( ...

How to Retrieve a Global Variable in an Angular Template

Is there a way to access a global variable from an Angular template? let unableToAccess = false; @Component({ selector: 'app-payment', templateUrl: './buy.component.html', styleUrls: ['./buy.component.scss'] }) export ...

Incorporate the Input() component into your codebase and take advantage of its dot notation features, such as

Many Angular directives utilize dot notation options: style.padding.px style.padding.% attr.src In addition, libraries like flex-layout employ this for various responsive sizes: fxLayout.gt-sm fxAlign.sm Can the same concept be applied to a component&a ...

summing 3 numbers to a total of 100 percent

I am currently trying to calculate the percentages of different statuses based on 3 count values. Let's assume I have 3 statuses: 1) Passed 2) Failed 3) Skipped When dealing with only two cases, I was able to use a combination of the Floor and Ceil ...

The JavaScript function for converting a date to a local string in the format of DD MMM YYYY is causing an error message in the browser console stating that it is not a valid function

I am encountering an issue with formatting a date string. The date is currently in the format 2021-03-31T00:00:00, and I need it to be displayed as 31 Mar 2021. In my TypeScript code, I attempted to use the following function: const formattedDate = i.Susp ...

When using the Angular Material table with selection enabled, the master toggle functionality should always deselect the

I made modifications to the original Angular Material Table example - Stackblitz. In my version, when some rows are selected and the master toggle is clicked, all selected rows should be deselected (similar to Gmail behavior). The functionality works, but ...

What is the best way to represent a directory structure in JSON using a C# data type?

My directory structure is as follows: v1 file1.txt file2.txt common common.txt I need to create a C# function that can traverse this directory structure and generate JSON output. The expected JSON format is like this: { "v1&qu ...

Ways to attain a similar format - input map

After pressing the save button, I am aiming to achieve the following effect: "timeTable":{ "0": [{"from":"08:00","to":"12:00"}, {"from":"14:00","to":"18:20&q ...

Efficient Ways to Utilize Global CSS in an Angular Project Without CLI

I am utilizing ASP.NET MVC as the server and Angular as the client application. Instead of a static index.html file, I have index.cshtml. The styles I am using are global styles rather than component-scoped. My query revolves around working with a bunch ...

Mastering unit testing with Behaviour Subjects in Angular

I am looking to test the get and set methods of my user.store.ts file. The get() method is used to retrieve users, while addUsers() is utilized to add new Users to the BehaviorSubject. How can I accomplish this? import { Injectable } from '@angular/c ...

`How to utilize the spread operator in Angular 4 to push an object to a specific length`

One issue I'm facing is trying to push an object onto a specific index position in an array, but it's getting pushed to the end of the array instead. this.tradingPartner = new TradingPartnerModel(); this.tradingPartners = [...this.tradingPartner ...

Getting a "module not found" error in Next.js while trying to import a TypeScript

Check out this code snippet: // lib/customFunction.ts export function customFunction() { console.log("customFunction"); } // pages/homepage.tsx import { GetServerSideProps } from "next"; // works import { exampleFunction } from "../lib/exampleFile.js" ...