Determine the data type of an object key based on the value of another key within the same

Consider having an Object Type named Options, which consists of two keys:

  1. strategy: a function that takes one parameter of an unknown type
  2. parameter: the same type as the first argument of strategy

The desired functionality is as follows:

type FooParameter = { foo: string }
type BarParameter = { bar: string }

const fooOptions: Options = {
  strategy: (parameter: FooParameter) => {},
  parameter: { foo: 'foo' }
}
const barOptions: Options = {
  strategy: (parameter: BarParameter) => {},
  parameter: { bar: 'bar' }
}

It should be possible for TypeScript to infer the type of fooOptions.parameter from fooOptions.strategy and likewise for barOptions.parameter from barOptions.strategy.

Is this currently achievable with TypeScript?

Answer №1

To tackle this issue, the most viable approach I can think of is by utilizing a generic type. I highly doubt that there exists a solution where the compiler will validate that parameter is an appropriate argument for strategy without making use of a generic type.

type Options<T> = {
    strategy: (parameter: T) => void,
    parameter: T
}

This implies that when Options is applied in a type annotation, you are required to supply a type parameter:

const fooOptions: Options<FooParameter> = {
    strategy: (parameter: FooParameter) => {},
    parameter: { foo: 'foo' }
}

function useOptions<T>(o: Options<T>): void {
    o.strategy(o.parameter);
}

However, whenever the compiler can deduce the type (i.e. when no type annotation is utilized), it is not mandatory to explicitly define a type for the generic type parameter. Specifically, users of an API like the useOptions function can provide an object literal and benefit from type-checking and type inference:

useOptions({
    strategy: param => {
        let x = param.x; // Automatically inferred as number
        let y = param.y; // Automatically inferred as string

        // Error: Property 'z' does not exist on type '{ x: number, y: string }'
        let z = param.z;
    },
    parameter: { x: 1, y: 'foo' }
});

Keep in mind that the user in this scenario doesn't need to explicitly specify { x: number, y: string } or any equivalent type to utilize the API.

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

Using Angular's dependency injection in a project that has been transpiled with Babel

I am currently attempting to transpile my Angular 6 project, which is written in TypeScript, using the new Babel 7. However, I am facing challenges with getting dependency injection to function properly. Every time I try to launch the project in Chrome, I ...

What is the correct way to assign multiple types to a single entity in TypeScript?

(code at the end) While attempting to write section.full.link, I encountered the following error: Property 'link' does not exist on type 'SectionSingle | SectionTitle | SectionHeaderMedia'. Property 'link' does not exist on ...

Show the user's chosen name in place of their actual identity during a chat

I'm facing an issue where I want to show the user's friendly name in a conversation, but it looks like the Message resource only returns the identity string as the message author. I attempted to retrieve the conversation participants, generate a ...

Using TypeScript to implement functional props in React applications

When passing functional props from a parent to a child component with typescript: import react, {Component} from 'react' import Child from './Child' //some type declaration class Parent extends Component<{IProps},{IState}> { stat ...

Develop an enhancement for the Date object in Angular 2 using Typescript

Using the built-in Date type, I can easily call date.getDate(), date.getMonth()...etc. However, I am looking for a way to create a custom function like date.myCustomFunctionToGetMonthInString(date) that would return the month in a string format such as &a ...

Having trouble getting Angular Material's mat-autocomplete to function properly when the application is in

I am currently in the process of incorporating a mat-autocomplete field, following the guidelines provided in the documentation. Everything functions as anticipated when tested on ng serve. However, after running ng build --prod and deploying to Firebase, ...

The specified main access point, "@angular/cdk/platform", is lacking in required dependencies

I recently updated my Angular app from version 8 to version 9. After resolving all compilation and linter errors, I encountered one specific issue that is causing me trouble: ERROR in The target entry-point "@angular/cdk/platform" has missing dep ...

Get an angular xml file by utilizing the response from a C# web API download

I am trying to download an XML file from a database using a Web API in C#, which returns the file as byte[]. How can I properly read these bytes and convert them into an XML file on the client side using Angular? Despite attempts with blobs and other metho ...

Iterate over Observable data, add to an array, and showcase all outcomes from the array in typescript

Is there a way to iterate through the data I've subscribed to as an Observable, store it in an array, and then display the entire dataset from the array rather than just page by page? Currently, my code only shows data from each individual "page" but ...

Describe the TypeScript type for an object with constant keys

My query resembles the one found in this Typescript interface definition question, but has a slight variation. I am beginning with an object where the keys are constants: const KEYS = { KEY1: 'hello', KEY2: 'world' } as const; How ...

Implementing the breadcrumb component within dynamically loaded modules loaded through the router-outlet component

I'm currently working on an angular 8 breadcrumb component for my application. The requirement is to display it in the content of the page, not just in the header, and it should never be located outside the router-outlet. This has posed a challenge fo ...

extracting the HTML content from JavaScript and saving it into a standalone file

update When I click a link, a popup opens and I see all this HTML. The smile method is called when I click the link, and we append HTML in that method so that we can see it when the popup is opened. I moved it to a separate file something.component.html, ...

Error TS2559 occurs when the type '{ children: never[]; }' does not share any properties with the type 'IntrinsicAttributes & { post?: IPost | undefined; }'. This discrepancy in properties causes a type mismatch in the code

I'm having trouble understanding what the problem is. I have already looked at answers to this Error here, and I noticed that one of the issues others faced was a repetition of a function name and not giving props to a component in the component tree. ...

"This error message states that the use of an import statement outside a module is not allowed

After searching for a solution without any luck, I decided to start a new discussion on this topic. Currently, I am working on azure functions using Typescript and encountering the following error: import { Entity, BaseEntity, PrimaryColumn, Column, Many ...

The value of req.headers('Authorization') has not been defined

I'm experiencing difficulty with my code as the token is coming back as undefined. Here is the frontend section: export const fetchUser = async (token: any) => { const res = await axios.post('/user/getuser', { headers ...

Angular - Showing validation messages post successful execution of two functions

I have encountered an issue with my form submission process involving two functions. When both functions succeed, I want to display a successful validation message. However, currently the success message is displayed even if the second function fails. How ...

When attempting to loop through an Observable that is of type array using *ngFor, the error message "Cannot read property 'subscribe' of undefined

I can't figure out why this isn't working, even though it seems straightforward. I'm using a service that gives me an observable. There are a few rxjs streams connected to it in the following way: search(searchTerm: string { this.search ...

Is there a way to identify the accurate or incorrect array element and modify the component color accordingly?

Upon reviewing the question alternatives, I encountered a problem where clicking on one of the buttons correctly indicated whether it was the correct or incorrect answer by changing its color. However, the issue is that all buttons are being affected by th ...

When implementing JSS with React and TypeScript, certain CSS properties may encounter a `type is unassignable` error

Recently delving into TypeScript, I've encountered an issue within my project that was created using create-react-app with TypeScript and incorporates JSS. It appears that certain CSS properties are causing errors. Specifically, the pointerEvents and ...

Interacting with a form input by triggering the onChange event

I am encountering a problem where I need to be able to select a radio button both onChange via keydown and mouse click. However, I am struggling with accessing both event parameters of the on keydown and on mouse click within the same function. As a result ...