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

Can you explain the distinction, if one exists, between a field value and a property within the context of TypeScript and Angular?

For this example, I am exploring two scenarios of a service that exposes an observable named test$. One case utilizes a getter to access the observable, while the other makes it available as a public field. Do these approaches have any practical distincti ...

Generating a JSON object through the comparison of two other JSON objects

I need to create a new JSON object called selectedProductAttributes, which is generated by comparing the contents of a second JSON object (selectedProductAttributesNames) with a third object (allProductAttributes). Let me provide some examples to make this ...

Custom Typescript type that runs concurrently with the base type is disregarded

Assumption: When creating a custom type that mirrors an existing type, the expectation is for variables assigned to that type to maintain it and not default back to the base type. In the function f provided below, the expected return type should be Dog ins ...

Sharing information between React components involves passing data as props. By sending data from

Brand new to React and still figuring things out. Here's the scenario: <div> <DropDown> </DropDown> <Panel> </Panel> </div> After selecting a value in the dropdown and storing it as currentL ...

"Converting jQuery Form into a Wizard feature with the ability to hide specific steps

I'm working on a form where I need to hide a fieldset when a specific event is triggered. Inside the first fieldset, there is a select tag and when a certain option is selected, the second fieldset should be hidden. <form id="form1"> <fi ...

"Despite modifying the ID in the response data of Angular MongoDB, the request data ID remains unchanged

Having trouble with managing requests and responses, specifically when a customer tries to add multiple items of the same product but in different sizes. The initial step involves checking if the ID exists by using a count and an if statement. If it exists ...

React, handling various router navigations

I have set up a BrowserRouter to serve /, /login, and /logout on my website. Once logged in, users can access an app with a consistent navbar on every page and dynamic content that holds data/functionality within the "Main" template component, which utiliz ...

Exploring .ENV Variables using Angular 2 Typescript and NodeJS

After completing the Angular2 Quickstart and tutorials, I'm now venturing into connecting to a live REST Api. I need to include authentication parameters in my Api call, and from what I've gathered, it's best practice to store these paramete ...

Using JavaScript to execute a JSON parse function will not work

I am currently working on this code and would appreciate any assistance. I'm trying to retrieve and parse data from my listApp.json file to display a list with one link. As a beginner, I could use some guidance. <script type = "text/javascript"> ...

One-of-a-kind npm module for typescript

As part of my project, I am enhancing an existing library to make it compatible with TypeScript. To showcase this modification, I have condensed it into a succinct Minimal working example The specified requirements To ensure backward compatibility, the li ...

What is the best way to iterate through data with ajax and mysql?

I have a school project where I need to create an MP3 album playlist using a premade PHP API with JavaScript or jQuery (without using PHP). I can input the data via an AJAX call. The goal is to add multiple songs along with their URLs into a column named s ...

When an Ajax call is made, my .html page transforms into a .php page using jQuery

The Issue While using my PHP function to send emails, everything goes smoothly. However, I'm facing an issue where I don't want the page to refresh, so I've implemented AJAX in the code below: reservation.html <form class="form-horizon ...

Image loading failure detected in ReactJS

In my current project using Reactjs (Nextjs framework), I encountered an issue where I am unable to display an image on a page without specifying the "height" and "width" attributes in the Image tag. I attempted the following code snippet but the image is ...

Different categories of properties within a generic function

I'm attempting to modify certain fields of my object using field names. Here is the code snippet I have written: interface Foo { a: number[], b: string[], } type Bar = { [T in keyof Foo] : (arg : Foo[T]) => Foo[T] } function test<T ex ...

Efficient Local Database with Javascript

When storing a substantial amount of data, such as a big hashmap in JavaScript, what would be the optimal format for quick retrieval while also supporting Unicode? Would XML or JSON be better suited for this purpose? ...

Customize AngularJS checkbox values when checked

Is there a way to set a checkbox to be checked by default with a custom value instead of a boolean value? Ready to go? <input type="checkbox" ng-model="checked" ng-init="checked=true" ng-true-value="sure" ng-false-value="nope"><br/> <tt> ...

Error code 405 (METHOD NOT ALLOWED) is received when attempting to make a post request to an API

Struggling to develop a basic front end that can communicate with my API. The API functions properly as I am able to retrieve and send data using the POSTMAN client. Fetching data from the server and displaying it on the frontend works fine, but encounteri ...

Executing a search within the current connection in Node.js

In the code snippet provided, the need is to execute the second SQL query (query2) after constructing it based on the results of the first query (query1). However, even though the second query is successfully built, it is not being executed. Assistance i ...

"Encountered an issue with ng-annotate during processing

I'm attempting to utilize ng-annotate on my Angular application, but it seems to be not working at all. Here is the configuration part: (function () { 'use strict'; angular.module('app') .config(/*@ngInject*/ ro ...

Transferring files via Bluetooth on PhoneGap

As someone new to phonegap, I'm interested in transferring text files from one device to another using Bluetooth within the platform. I've looked at several examples but haven't found a solution yet. I've come across some examples that ...