skip to Main Content

How to write definition of type in function argument which is one of object properties with same type?

Example:
I have object:

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

and want to write function which summarise price depending on price type property:

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

How definition of NeededProperty should look like to ensure typescript that it’s one of Article properties priceNet or priceGross and it is number type?

2

Answers


  1. Chosen as BEST ANSWER

    Previous answer by Yaman Abd is correct, but I found little more pretty solution:

    Solution

    type NeededType = keyof Pick<Article, 'priceNet' | 'priceGross'>;
    

    Explanation

    • keyof makes string type from one of given object properties
    • Pick is utility type that helps to select properties from Article type. So we are ensured that property is included in Article object type.

    This solution suggest properties which you can use while defining type NeededType.

    Example

    So proper example look like this:

    type Article = {
      name: string;
      quantity: number;
      priceNet: number;
      priceGross: number;
    };
        
    type NeededType = keyof Pick<Article, 'priceNet' | 'priceGross'>;
    
    function summarise(article: Article, priceTypeProperty: NeededType) {
      return article[priceTypeProperty] * article.quantity;
    }
        
    // Usage
    const myArticle: Article = {
      name: "Example Article",
      quantity: 5,
      priceNet: 10,
      priceGross: 12
    };
        
    const totalPriceNet = summarise(myArticle, "priceNet"); // Works
    const totalPriceGross = summarise(myArticle, "priceGross"); // Also works
        
    const totalPriceGross = summarise(myArticle, "otherPrice"); // does not work
    

  2. To achieve this you could use keyof and a type constraint to make sure that the parameter is one of the valid key names in the Article type and must be (priceNet or priceGross) and its a number type

    type Article = {
      name: string;
      quantity: number;
      priceNet: number;
      priceGross: number;
    };
    
    function summarise(article: Article, priceTypeProperty: keyof Article & ("priceNet" | "priceGross")) {
      return article[priceTypeProperty] * article.quantity;
    }
    
    // Usage
    const myArticle: Article = {
      name: "Example Article",
      quantity: 5,
      priceNet: 10,
      priceGross: 12
    };
    
    const totalPriceNet = summarise(myArticle, "priceNet"); // Works
    const totalPriceGross = summarise(myArticle, "priceGross"); // Also works
    
    const totalPriceGross = summarise(myArticle, "otherPrice"); // does not work
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search