Different kinds of functions can take an optional property name as an argument and either return the value of that property in an object or the entire object itself

In need of a function that accepts an optional parameter propName, which must be a key belonging to SOME_OBJECT. The function should return the value of propName if it is provided, or else return the entire OBJECT:

Here's the code snippet:

type SOME_OBJECT = {
  propA: string,
  propB: number,
}

const getPropertyOrFullObject = <K extends keyof SOME_OBJECT>(propName?: K)
: SOME_OBJECT[K] | SOME_OBJECT => {

  const myData: SOME_OBJECT = {  
    propA: "fooA",
    propB: 42
  };

  if (propName) {
    return myData[propName];
  }
  else {
    return myData;
  }
};

const propA = getPropertyOrFullObject("propA"); 
const propB = getPropertyOrFullObject("propB"); 
const fullObj = getPropertyOrFullObject();       

Code can be viewed on Typescript playground

Received unexpected results instead of what was expected. Union types were returned. Check below for details:

https://i.sstatic.net/OUkvm.png

https://i.sstatic.net/FR3lE.png

https://i.sstatic.net/nohyK.png

Answer №1

TS struggles to determine the exact return type of a function, which leads it to merge all possible returns.

To simplify this, it is recommended to use function overloading as a good practice.

Consider the following example:

type SOME_OBJECT = {
  propA: string,
  propB: number,
}

// introducing a new player
interface Overloading {
  <K extends keyof SOME_OBJECT>(propName: K): SOME_OBJECT[K]
  (): SOME_OBJECT;
}

const getPropertyOrFullObject: Overloading  = <K extends keyof SOME_OBJECT>(propName?: K)
: SOME_OBJECT[K] | SOME_OBJECT => {

  const myData: SOME_OBJECT = {  // ACTUAL DATA WILL BE RETRIEVED FROM ANOTHER SOURCE
    propA: "fooA",
    propB: 42
  };

  if (propName) {
    const result = myData[propName];
    return myData[propName];
  }
  else {
    return myData;
  }
};

const propA = getPropertyOrFullObject("propA");  // returns a string
const propB = getPropertyOrFullObject("propB");  // returns a number
const fullObj = getPropertyOrFullObject();       // returns an object of type SOME_OBJECT

Answer №2

After reading @captain-yossarian's response, I decided to implement the following:

type SOME_OBJECT = {
  propA: string,
  propB: number,
}

function getPropertyOrFullObject(): SOME_OBJECT;
function getPropertyOrFullObject<K extends keyof SOME_OBJECT>(propName: K): SOME_OBJECT[K];
function getPropertyOrFullObject<K extends keyof SOME_OBJECT>(propName?: K): SOME_OBJECT | SOME_OBJECT[K] {

  const SOME_OBJECT: SOME_OBJECT = {  // THIS WILL BE FETCHED FROM AN EXTERNAL SOURCE
    propA: "fooA",
    propB: 42
  };

  return propName ? 
    SOME_OBJECT[propName] 
  : SOME_OBJECT;

}

const propA = getPropertyOrFullObject("propA");   // RETURNS AS A string
const propB = getPropertyOrFullObject("propB");   // RETURNS AS A number
const fullObj = getPropertyOrFullObject();        // RETURNS AS THE WHOLE OBJECT

I find that this approach improves the readability and comprehension of the overload method.

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

Refreshing issue: Model change in child page not updating view correctly (Ionic & Angular)

I am currently working with Ionic 3.20 and Angular 5.2.9, encountering an issue with content refreshing after a model change. Despite being new to this, I sense that I might be overlooking something fundamental. Within my view, I have the following elemen ...

Is there a way for me to implement a feature akin to the @deprecated annotation?

In my TypeScript Next.js application, I rely on Visual Studio Code for coding purposes. One feature that I particularly enjoy is the ability to add a JSDoc annotation of @deprecated above a function, which then visually strikes through the function name t ...

Shared validation between two input fields in Angular 2+

I have a unique task at hand. I am working on creating an input field with shared validation. The goal is to ensure that both fields are technically required, but if a user fills in their email address, then both fields become valid. Similarly, if they ent ...

Choosing the open status of an HTML list

Is there a way to determine which containers in a list are currently open and which ones are still closed? Currently, I am utilizing the slideDown(), slideDown(), and addClass functions on divs with the specific class="section_hdl_aktiv". However, I want ...

The bootpag event seems to trigger multiple times upon execution following an Ajax function call

I have integrated the bootpag jQuery pagination plugin from bootpag into my .NET/jQuery project. Within my project, there is a filtering menu that triggers an Ajax call to update the page with filtered or paginated data when a user selects a filtering opti ...

I prefer not to run the next.js SWR until after the initial rendering

Development Setup ・ next.js ・ typescript ・ swr This uses swr for communication purposes. I am looking to only trigger it when the query value changes. However, it is also being executed during the initial rendering. How can I prevent it ...

Most effective method to verify if mutation observer meets specific criteria

I have set up a mutation observer to monitor changes in the page load. Specifically, I am interested in detecting the moment when a particular element is loaded or exists. This element can be identified by its classname, let's say it's called foo ...

What is the syntax for implementing a for loop/for each loop in EJS?

I'm trying to figure out how to include this code snippet inside <% %>. I'm not sure if it's similar to a typical forEach/for loop. The documentation on EJS site is quite limited, so I've turned to this forum for help. <% incl ...

Executing a series of actions in React redux synchronously

https://i.sstatic.net/QnZew.png Within the store, there exists an array named visited:[]. Inside a function titled changeInfo, the first task is to clear the array followed by adding an item to it. const changeInfo = (value) => { dispatch(clearVis ...

Exploring the optimal approach for distinguishing between numbers and strings in a JavaScript/Typescript class

I recently encountered a situation with my Typescript/React solution where I defined a property as a number and set the input type to "number", but when the state value was placed in an input field, it would change to a string unless properly handled. In ...

How can Sequelize be used to effectively set up User Data with specific constraints?

This particular query isn't looking for the "best practice" answer, but rather a more suitable solution compared to what I currently have. Essentially, I have a User model/table that is associated with the UserScore model/table. User.belongsTo(model ...

Eliminate Redundancy with Knockout.js Copy Prevention

When I combine both ko.js files, one of them ends up being overshadowed by the other. Specifically, the second one stops working while only the first one remains functional. How can I merge these files together to ensure they work properly without any conf ...

npm ERROR! 404 Content removed by unidentified source on August 8, 2022 at 09:20:35.527 UTC

Upon running the command <npm view e-biz-znnf versions --json> in the terminal, npm throws an error message: npm ERR! code E404 npm ERR! 404 Unpublished by undefined on 2022-08-08T09:20:35.527Z npm ERR! 404 npm ERR! 404 'e-biz-znnf' is no ...

Having Trouble Styling Radio Buttons with CSS

Hello, I'm facing an issue with hiding the radio button and replacing it with an image. I was successful in doing this for one set of radio buttons, but the second set in another row is not working properly. Additionally, when a radio button from the ...

Ways to access dropdown menu without causing header to move using jQuery

Greetings everyone, I am currently working on a dropdown language selection feature for my website. The issue I am facing is that when I click on the language dropdown in the header, it causes the height of the header to shift. $('.language- ...

Preventing Double Click Events on jQuery Spinner

I have been working on an option picker, but now there is a new requirement to make the options configurable. While this shouldn't be too difficult, I am facing some issues with the option picker: Currently, when an item is double-clicked, it will ge ...

Runtime error caused by incorrect Typescript version detected in Visual Studio Code

After updating to VSCode 1.6.1 and switching from Typescript 1.8.10 to 2.0.3, my project stopped working. The Reflect methods have changed causing Routing-Controllers to throw an error when trying to get method attributes: TypeError: Reflect.getMetadata ...

Struggling to implement a Datepicker in the date column of a table created using HTML and JavaScript

I am encountering an issue while creating a table in html and javascript. I am unable to use a Datepicker in the date column when inserting a new row, even though it works fine when using in normal html code. Below is the javascript function: //Script fo ...

The lodash debounce function is being triggered multiple times instead of just once, causing issues with my react hooks in a react native environment

Currently, I am implementing a search feature for multiple objects in an array that triggers onChange of the text Input. To optimize this process, we need to incorporate a debouncing function to prevent unnecessary API calls to the search function. Howeve ...

Issue with jQuery functionality when page is loaded through AJAX request

My index page currently has jQuery and a js file for a slider plugin loaded. I am using an on click event to load an external page using .load. Here is the code snippet: //jQuery loaded from Google CDN here (in head) jQuery( document ).ready(function() { ...