Guide on retrieving the interface property name or key name as a string in Typescript

Currently, I am utilizing the API of Slack and encountering situations where I send JSON requests containing strings that return as property names later on.

I want to create an interface where I can send one of its property names as a string and receive the returning object with correct typing without relying on "magic strings" or constants that need to stay synchronized with the interface.

Here's a quick example:

// Sending out this request to Slack
const request = {
    actionId: "specialProperty"
};

// Later, Slack might return this object
const incomingWebhook = {
    specialProperty: "Value I want to read"
}

I can easily define typing for this using an interface

interface SpecialPropertyInterface {
  specialProperty: string;
}

My concern is that this interface is tied to the string I send out.

Is there a way for me to extract the key/property "specialProperty" from my SpecialPropertyInterface as a string?

Answer №1

I was able to find a solution to my problem using the "keyof" method. Although not perfect, it allowed me to obtain a type-safe string based on an interface property.

Since I had two nested keys, I decided to separate them into two interfaces and utilize keyof to retrieve the string representation of each property.

export interface HoursBlock {
  hours: HoursBlockAction;
}

export interface HoursBlockAction {
  hoursAction: {
    // eslint-disable-next-line camelcase
    selected_option: {
      value: string;
    };
  };
}

...

// The following strings will only be valid if they correspond to the property names.
const hoursBlockId: keyof HoursBlock = "hours";
const hoursActionId: keyof HoursBlockAction = "hoursAction";

// Any deviation from the correct string will result in an error.
// Type '"wrong"' is not assignable to type '"hours"'.ts(2322)
const wrongHoursBlockId: keyof HoursBlock = "wrong";

Answer №2

Let's give this a shot.

To start, append as const to the declaration of your request object:

const request = {
    actionId: "specialProperty"
} as const;

By doing so, the type of the actionId property becomes a literal ("specialProperty") instead of a regular string:

type RequestActionId = typeof request["actionId"] // "specialProperty"

Now, we can utilize it in a mapped index signature:

type SpecialPropertyInterface = {
  [propName in RequestActionId]: string; // specialProperty: string
}

Playground Link

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 could be the reason my mat-form-field is not displaying the label?

I'm currently working on a project using Angular Material to build a web page. I am facing an issue with the mat-form-field component as the label is not displaying, and I can't figure out why. Any assistance would be greatly appreciated. Thank y ...

How can you properly structure chainable functions in Angular?

Recently, I've been working on developing custom functions for my Angular application. Following the official guidelines, I have created an independent library. My goal is to create chainable functions similar to this: var obj = { test : function( ...

Expo constants failing to load on web due to unresolved manifest object issue

When setting up Firebase Auth in my expo app (using Google Auth), I needed to store my firebase variables in a .env file containing API_KEYS, AuthDomain, and more. To access these environment variables, I utilized expo constants in my firebase.ts file. Ini ...

Sass Alert: The mixin called roboto-family is missing from the stylesheet. Trace: Problem detected in src/pages/forms/forms.scss at

Greetings, I am diving into the world of Ionic for the first time. Recently, I embarked on a new project in Ionic and decided to integrate a theme. To do so, I copied an .html file, an .scss file, and also created a .ts file. Forms.html <!DOCTYPE html ...

A different approach to handling multiple constructors in Angular 4

Angular 4 does not support having multiple constructors, so I need to find a cleaner way to instantiate my object. This is what my model looks like: export class SrcFilter { constructor(public firstList?: Array<String>, public secondList?: Arra ...

Unable to create property within array in model

I am facing an issue while trying to access the name property of an array called Model[] generated from my Model.ts file. When attempting to use it in my app.component, I receive an error stating that the property 'name' does not exist on type Mo ...

Steps for building a TypeScript project for server side using webpack

After configuring webpack to compile my project using TypeScript, I encountered an issue. The project is a server-side Node project that needs to be used as a linked library by another server-side project. When I compile it with webpack, I receive a window ...

Exploring the power of NestJS integration with Mongoose and GridFS

I am exploring the functionality of using mongoose with NestJs. Currently, I am leveraging the package @nestjs/mongoose as outlined in the informative documentation. So far, it has been functioning properly when working with standard models. However, my p ...

Error in TypeScript: The property 'data' is not found within type '{ children?: ReactNode; }'. (ts2339)

Question I am currently working on a project using BlitzJS. While fetching some data, I encountered a Typescript issue that says: Property 'data' does not exist on type '{ children?: ReactNode; }'.ts(2339) import { BlitzPage } from &q ...

ERROR Error: Uncaught (in promise): ContradictionError: The variable this.products is being incorrectly identified as non-iterable, although it

Seeking a way to extract unique values from a JSON array. The data is fetched through the fetch API, which can be iterated through easily. [please note that the product variable contains sample JSON data, I actually populate it by calling GetAllProducts( ...

Ways to retrieve the value of the variable within the confines of this particular

In my code, I have private variables in the constructor and public variables in the class. To reference these variables and functions, I use the "this" keyword. However, when trying to access these variables inside a function, I am getting an "undefined" ...

Transforming a JSON object into XML format

Currently, I am encountering an issue while attempting to convert my JSON object to XML using the xml-js library's json2xml function. When trying to implement this functionality, I keep getting an error message that states: Error: Buffer is not defin ...

Error: WebStorm's Language Service has timed out while executing TSLint operations

While working on my Mac running MacOS Sierra with WebStorm (version 2017.2.4), I encounter a pop-up notification sporadically, as shown in the following image: My coworkers and I all have the same TSLint configuration and code style set up in WebStorm. Ho ...

How to verify in HTML with Angular whether a variable is undefined

When it comes to the book's ISBN, there are instances where it may not be defined. In those cases, a placeholder image will be loaded. src="http://covers.openlibrary.org/b/isbn/{{book.isbn[0]}}-L.jpg?default=false" ...

Tips for setting values to the child component property in Angular 4

When I was using ngif, I encountered an issue with getting the element reference of the child component. After extensive searching, I discovered that in order to access the element, I needed to use view children instead of view child. While I am able to ge ...

Utilizing client extension for Postgres with Prisma to activate RLS: A step-by-step guide

Recently, I attempted to implement client extension as advised on Github. My approach involved defining row level security policies in my migration.sql file: -- Enabling Row Level Security ALTER TABLE "User" ENABLE ROW LEVEL SECURITY; ALTER TABLE ...

Guiding you on exporting a Typescript class with parameters in Node.js

Trying to find the Typescript equivalent of require('mytypescriptfile')(optionsObject); This is the TS code provided: export class Animal { name: string; public bark(): string { return "bark " + this.name; } constructor(color:string) ...

I am in need of a customized 'container' template that will display MyComponent based on a specific condition known as 'externalCondition'. MyComponent includes the usage of a Form and formValidation functionalities

container.html <div ngIf="externalCondition"> <!--Initially this is false. Later became true --!> <my-component #MyComponentElem > </my-component> <button [disabled]= "!myComponentElemRef.myDetailsF ...

I encountered an issue with my TypeScript function in Angular, as it is unable to process multiple uploaded files

I'm having trouble with my TypeScript function in Angular that is unable to read multiple uploaded files. fileUpload(event: Event) { const self = this; this.imageUploadInp = event.target as HTMLInputElement; this.imageUploadInp.addEventLis ...

Accessing the Component Property from an Attribute Directive in Angular 2

Currently, I am in the process of creating filter components for a grid (Ag-Grid) and planning to use them in various locations. To make these filters accessible from different places, I am developing a wrapper for them. In particular, I am working on a fi ...