Navigating through nested objects in a combined type

Is there a way to create a function that can take an object (which is part of a union) with a specified path and return the value of the config object for that specific path?

I've been attempting the following:

type Cat = {
  config: {
    meow: string;
  };
};

type Dog = {
  config: {
    woof: string;
  };
};

type Animal = Cat | Dog;

const getProperty = <T extends Animal>(obj: T, path: keyof T["config"]) => {
  // I'm encountering an error at this stage:
  // "Type 'keyof T["config"] cannot be used to index type '{ meow: string; } | { woof: string }'
  return obj.config[path];
};

However, if I try implementing a similar function to access fields at the root level (instead of within the config object), it works without any issues:

type Cat = {
  meow: string
}

type Dog = {
  woof: string
}

type Animal = Cat | Dog

const getProperty = <T extends Animal>(obj: T, path: keyof T) => {
  return obj[path]
}

I believe the problem lies in using keyof on the object field of a Union type, but the exact reason eludes me.

Answer №1

While it may not be flawless, this code snippet appears to achieve the intended functionality based on my experimentation:

const getProp = <T extends TypeA, K extends keyof T['options']>(obj: T, key: K): T['options'][K] => {
    return (obj['options'] as T['options'])[key];
};

I validated this by executing the following test:

const result = getProp({ options: { value: 'hello' } }, 'value');
console.log(result);

The above code should display hello.

Answer №2

If you wish to modify your function, consider the following alternatives:

const property = (obj: Baz, path: keyof Baz["config"]) => {
  return obj.config[path];
};

or:

const property = <T, K extends keyof T>(obj: { config: T }, path: K) => {
    return obj['config'][path];
};

Explore in Playground

Regarding the issue with indexing type using keyof T["config"], it appears to be a design constraint.

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

Trouble with Mui theme not being applied when inside a wrapper component

In my project using React with typescript and MUI version 5.4.2, I have been attempting to manage all styles in a single file by enclosing everything inside my App.tsx component. Problem: The custom MUI theme is not being applied throughout my application ...

Creating a TypeScript function that automatically infers the type of the returned function using generics

Suppose I want to execute the generateFunction() method which will yield the following function: // The returned function const suppliedFunction = <T>(args: T) => { return true; }; // The returned function // This is how it can be used suppli ...

The service fails to recognize the ActivatedRoute

Using ActivatedRoute in Services The Challenge Attempting to utilize ActivatedRoute within a service, I encountered an issue where it was not tracking the current route accurately. It seemed unable to detect any route at all. After spending considerable ...

Exploring the traversal of an array of objects within Tree Node

How can I transform my data into a specific Tree Node format? Is there a method (using Typescript or jQuery) to iterate through each object and its nested children, grandchildren, and so on, and modify the structure? Current data format { "content" ...

"Implementing a retry feature for Angular http requests triggered by a button

Imagine having a situation where a component has a method that triggers an http request defined in a service. The observable is subscribed to within the component: Component: fetchData() { this.apiService.fetchDataFromServer().subscribe( respo ...

"Implementing a loop to dynamically add elements in TypeScript

During the loop session, I am able to retrieve data but once outside the loop, I am unable to log it. fetchDetails(){ this.retrieveData().subscribe(data => { console.log(data); this.data = data; for (var k of this.data){ // conso ...

Display the modal in Angular 8 only after receiving the response from submitting the form

I am encountering an issue where a pop-up is being displayed immediately upon clicking the submit button in Angular 8, before receiving a response. I would like the modal to only appear after obtaining the response. Can someone assist me with achieving thi ...

The type 'number' cannot be assigned to the type 'Element'

Currently, I am developing a custom hook called useArray in React with TypeScript. This hook handles array methods such as push, update, remove, etc. It works perfectly fine in JavaScript, but encounters errors in TypeScript. Below is the snippet of code f ...

The process of compiling and monitoring *two* Typescript packages, where one is reliant on the other

I'm in the process of creating a Typescript library located under src/ and sample files under examples/. The current directory structure is as follows: examples/ package.json exampleFiles.ts src/ index.ts package.json I am able to compil ...

The name 'Queue' cannot be located in Typescript, error code ts(2304)

I'm currently trying to create a private variable of type InnerItem, but I keep encountering the following error: Error: Cannot find name 'Queue'.ts(2304) private savedItems: Queue<InnerItem> = new Queue<InnerItem>(20); Could ...

Some files are missing when performing an npm install for a local package

My project is structured like this: ├── functions/ │ ├── src │ ├── lib │ ├── package.json ├── shared/ │ ├── src │ | ├── index.ts | | ├── interfaces.ts | | └── validator_cl ...

Ways to trigger a function in Angular every 10 seconds

What is the method to utilize Observable function for fetching data from server every 10 seconds? Custom App service fetchDevices (): Observable<Device[]> { return this.http.get(this.deviceUrl) .map(this.extractData) .catch(this ...

Hold off until all commitments are fulfilled in Firestore

Is there a way to ensure that all promises are resolved before moving on to the next line of code? Currently, it seems like it's moving to the next line without completing the operation below. I want to make sure that the forEach loop is fully execute ...

Tribal Code Typescript Compiler

Typescript is a great alternative to Javascript in my opinion, but it bothers me that it requires node.js as a dependency. Additionally, I find it frustrating that there seems to be only one compiler available for this language, and it's self-hosted. ...

"Take control of FileUpload in PrimeNG by manually invoking it

Is there a way to customize the file upload process using a separate button instead of the component's default Upload button? If so, how can I achieve this in my code? Here is an example of what I've attempted: <button pButton type="button" ...

The React Typescript error message: "Type '' is not compatible with type 'null'"

I have started working on a simple todo app using React and TypeScript. As I am creating a context, I encountered an error regarding the value of the content provider. <TodoContext.Provider value={contextValue}>{children}</TodoContext.Provider> ...

Encountering an endless loop within a data rest API in a React application

Currently, I am in the process of learning React and attempting to utilize the Poke API with my application. Unfortunately, I seem to have run into an infinite loop issue and I am feeling quite lost in terms of troubleshooting it. Below is a snippet of my ...

Create a Bar Graph Using a List

Looking to generate an Angular Barchart from a JPA query in Spring: public List<PaymentTransactionsDailyFacts> findPaymentTransactionsDailyFacts(LocalDateTime start_date, LocalDateTime end_date) { String hql = "SELECT SUM(amount) AS sum_volume, ...

Issue with TypeScript not detecting exported Firebase Cloud Functions

Dealing With Firebase Cloud Functions Organization I am managing a large number of Firebase Cloud Functions, and in order to keep the code well-structured, I have divided them into separate files for each function category (such as userFunctions, adminFun ...

What makes TS unsafe when using unary arithmetic operations, while remaining safe in binary operations?

When it comes to arithmetic, there is a certain truth that holds: if 'a' is any positive real number, then: -a = a*(-1) The Typescript compiler appears to have trouble reproducing arithmetic rules in a type-safe manner. For example: (I) Workin ...