Using TypeScript, you can pass an object property name as a function argument while ensuring the type is

How can I define a type in a function argument that corresponds to one of the object properties with the same type?

For instance, if I have an object:

type Article = {
  name: string;
  quantity: number;
  priceNet: number;
  priceGross: number;
};

and I want to create a function that calculates the total price based on a specific price type property:

function calculateTotalPrice(article: Article, priceTypeProperty: NeededProperty) {
  return article[priceTypeProperty] * article.quantity;
}

What should the definition of NeededProperty be in order to ensure TypeScript that it matches either the priceNet or priceGross property within the Article object and has a data type of number?

Answer №1

In order to accomplish this task, you can utilize the `keyof` operator in conjunction with a type constraint to ensure that the parameter corresponds to one of the valid key names defined in the `Article` type. It must be either `priceNet` or `priceGross`, and it should have a data type of `number`.

type Article = {
  name: string;
  quantity: number;
  priceNet: number;
  priceGross: number;
};

function calculateTotal(article: Article, selectedPriceType: keyof Article & ("priceNet" | "priceGross")) {
  return article[selectedPriceType] * article.quantity;
}

// Example of how to use the function
const myArticle: Article = {
  name: "Sample Item",
  quantity: 3,
  priceNet: 15,
  priceGross: 18
};

const totalNetPrice = calculateTotal(myArticle, "priceNet"); // This works fine
const totalGrossPrice = calculateTotal(myArticle, "priceGross"); // Works as expected

const totalPriceOther = calculateTotal(myArticle, "anotherPrice"); // This will not work

Answer №2

Yaman Abd's previous answer is accurate, however, I have found a slightly more elegant solution:

Resolution

type DesiredType = keyof Pick<Item, 'costNet' | 'costGross'>;

Description

  • keyof converts a property of an object into a string type
  • Pick is a utility type that facilitates the selection of properties from the Item type. This guarantees that the property is part of the Item object type.

This solution proposes the properties that can be utilized when defining the DesiredType.

Illustration

An appropriate example would resemble this:

type Item = {
  label: string;
  quantity: number;
  costNet: number;
  costGross: number;
};
    
type DesiredType = keyof Pick<Item, 'costNet' | 'costGross'>;

function calculate(item: Item, costTypeProperty: DesiredType) {
  return item[costTypeProperty] * item.quantity;
}
    
// Implementation
const myItem: Item = {
  label: "Example Label",
  quantity: 5,
  costNet: 10,
  costGross: 12
};
    
const totalCostNet = calculate(myItem, "costNet"); // Functions correctly
const totalCostGross = calculate(myItem, "costGross"); // Also functions as expected
    
const totalOtherPrice = calculate(myItem, "otherCost"); // does not function properly

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

Is there a way to retrieve values from TextFields and Select elements by simply clicking on a button?

I am currently working on a project using react, redux, and material ui. I need to retrieve data from a TextField in order to make an order. The code snippet below showcases my current implementation: <Select value={product.color_set[0].title}> { ...

Disabling the search function when it is clicked (before any actions are taken)

I've recently implemented a search form on my website, where the search field opens up upon clicking the search icon.https://i.stack.imgur.com/UeErx.png To make the search icon clickable, I disabled the search function. var $searchBtn = $search.find ...

What is the proper method for effectively employing destructuring?

I'm trying to figure out how to properly return state with a fetched array using the spread operator. Here is my reducer code snippet: function themes(state = [], actions){ switch(actions.type){ case FETCH_THEMES_SUCCESSFULLY: const { th ...

AngularJS directive that performs asynchronous validation upon blur

I'm working on developing a directive that validates email addresses provided by users through asynchronous web requests. While the functionality is sound, I've encountered an issue where asynchronous calls are triggered every time a user types a ...

Enhance the sent server parameters by including extra options in fineuploader

I have successfully implemented file uploads using . Everything works perfectly. I am able to set parameters in the request object to send additional data to the server. However, when I try to add another parameter dynamically using the setParams function ...

Here's a revised version: "How to link a lambda layer with a function in a serverless.ts file using the

When working with the serverless framework using the typescript template, a serverless.ts file is generated. I am currently integrating lambda layers with existing functions and encountering a typescript error. The error message reads: "Type '{ Ref: ...

What is the correct way to specify type hints for a Stream of Streams in highlandjs?

I'm currently working with typescript@2 and the highlandjs library. In the typings for highland, there seems to be a missing function called mergeWithLimit(n). This function: Accepts a Stream of Streams, merges their values and errors into a single ...

Leveraging Angular 2 and RxJs 5 beta observables to continuously stream data from a while loop

I am looking to develop a straightforward Angular 2 application that calculates prime numbers within a while loop and continuously updates the view with newly discovered values. My goal is to showcase the list of prime numbers using *ngFor in real-time, gi ...

Converting a string array to an array object in JavaScript: A step-by-step guide

My task involves extracting an array from a string and manipulating its objects. var arrayString = "[{'name': 'Ruwaida Abdo'}, {'name': 'Najlaa Saadi'}]"; This scenario arises when working with a JSON file where ce ...

What is the best way to execute individual API requests for various sheets within the same spreadsheet?

I am currently working on integrating the Google Sheets API with Node.js. I need assistance with understanding the correct syntax for calling two separate sheets within one spreadsheet. After reaching out to chatgpt and gemini, I received conflicting answe ...

Two distinct controllers: concealing elements through the operation of one of them

I am facing a challenge with my HTML elements: In one form-group, I have the following input: <div class="form-group"> <input type="search" ng-model="search"/> </div> This particular form-group needs to be hidden when another form-g ...

Add a unique CSS style to both text and image using anchor tags

Why isn't the hover effect of color transition and underline being applied to the image? It seems to only work for text. While I understand that the color transition may require a change in image color, shouldn't the underline still occur? This ...

Converting a TypeScript object into a JSON string

When working with TypeScript, I am facing a challenge while trying to initialize an object that requires a JSON string for the "options" parameter. Specifically, it pertains to the object mentioned here. It is crucial that the options parameter be in JSON ...

Store the numeric value in JavaScript as a PHP integer

My goal is to obtain the width of the browser and then compare it as a PHP variable. However, the issue I am facing is that it is being saved as a string, and my attempts at parsing it to another variable only result in returning 0. $tam='<script& ...

Guide on using JSZip and VUE to handle an array of promises and store them in a local variable

My lack of experience with async functions has me feeling a bit lost right now... I'm attempting to loop through files in a folder within a zip file using JSZip, store these files in an array, sort them, and then save them to a local variable for furt ...

How to Access a div from another website using jQuery

I have a question. How can I call a div from another website using JavaScript? Here is the page: Now, I want to call the <div id="testa"> in another page. The other page is called Otherpage.html: jQuery(function($){ $(&ap ...

Guide to iterating through different endpoints in a predetermined sequence

I am facing a challenge with testing various endpoints using different login credentials. When looping through the endpoints, the results are not appearing in the sequential order due to asynchronous nature. My goal is to iterate through each endpoint wit ...

Unforeseen alterations in value occur in JavaScript when converting to JSON format

Having trouble generating a gantt chart from a JSON string, specifically with parsing the JSON string into a JSON object. I have a variable myString containing a JSON string that looks like this: {"c": [{"v": "496"}, {"v": "Task name 1"}, {"v": "9, "}, { ...

Step-by-step guide on how to have an AngularJS controller run continuously every 5 seconds once it has been initially called

My angular js file (app.js) contains the uuidCtrl controller, which triggers when called. When I want to call the controller 2 times, I have to load the page twice. However, I am looking for a solution to run it continuously after the first time it is call ...

The printing function for the window system can cause disruptions to the layout of the table

After creating a page with a simple table that can be filled in and printed, I noticed some issues with the table formatting after printing. The intended table design was supposed to look like this: https://i.stack.imgur.com/aAk89.png However, upon print ...