Determine data type using the generic type of a related property in Typescript

I am seeking a method to specify the type of a property based on the generic type of another property within the same context.

For instance, consider the following:

type Person = {
  id: number;
  name: string;
}

type Select<Value=unknown> = (props:Props<Value>) => any;

const PersonSelect:Select<Person> = (props) => null //implementation is irrelevant
const TextSelect:Select<string> = (props) => null //implementation is irrelevant


In this scenario, I aim to achieve something similar to the following:


type Filter<V = unknown > = {
  component: Select<V>,
  transformer: (value: V) => string
};

const filters:Array<Filter> = [
  {
    component: PersonSelect,
    transformer: (selected) => selected.name //the type of `selected` should be inferred as `Person`
  },
  {
    component: TextSelect,
    transformer: (selected) => selected //the type of `selected` should be inferred as `string`
  }
]


Potential Solution

To address the situation described above, the following approach can be adopted:



const personFilter:Filter<Person> = {
    component: PersonSelect,
    transformer: (selected) => selected.name
}
const textFilter:Filter<string> = {
    component: TextSelect,
    transformer: (selected) => selected
}

const filters = [personFilter, textFilter];

However, I am interested in finding a solution that does not require explicitly defining the type for each filter object. Additionally, since the generic `V` type can vary, utilizing a union of all conceivable combinations is not feasible. Are there alternative approaches available?

Answer №1

It appears that TypeScript is struggling to infer the arrow function property argument based on another property of the same object.

I tried using function inference but was unsuccessful.

An easy solution is to create a builder function that returns Filter<_>.


type Person = {
  id: number;
  name: string;
}

type Props<T> = T

type Select<Value = unknown> = (props: Props<Value>) => any;

const PersonSelect: Select<Person> = (props) => null //implementation is irrelevant

const TextSelect: Select<string> = (props) => null //implementation is irrelevant

type Filter<V = unknown> = {
  component: Select<V>,
  transformer: <T extends V>(value: T & V) => string
};


const builder = <V,>(
  component: Select<V>,
  transformer: (value: V) => string
): Filter<V> =>
  ({ component, transformer })

const filters = [
  builder(PersonSelect, (selected) => selected.name),
  builder(TextSelect, (selected) => selected)
]

Playground

Since component and transformer arguments are not within the same data structure, it simplifies the inference process and allows us to apply our type constraints more easily.

Here, you can explore additional examples of type inference on function arguments.

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

Tips for troubleshooting TypeScript integration tests within Pycharm

Currently, I have been utilizing PyCharm to code in typescript. To run tests in the integration directory, I execute npm run test:integration. However, I am now looking to debug the tests. The directory structure looks like this: my_project /src /tests ...

Retrieve the value from an HTML class using Angular

The Person Object has a field called schoolId, but the School object (not shown here) contains the schoolName. I want to display the schoolName in the table data cell instead of the schoolId from the Person Object. How can I achieve this? <tr *ngFor=& ...

Material-UI chart displays only loading lines upon hovering

Currently, I am utilizing a Material UI Line chart in my NextJS 14 application to showcase some data. Although the data is being displayed properly, I have encountered an issue where the lines on the chart only render when hovered over, rather than appeari ...

Creating a new endpoint within the Angular2 framework using typescript

I am brand new to Angular2 and I would like to streamline my API endpoints by creating a single class that can be injected into all of my services. What is the most optimal approach for achieving this in Angular2? Should I define an @Injectable class sim ...

Loading dynamic content within Angular Material tabs allows for a more customized and interactive user experience

I am currently working on creating a dynamic tab system using Angular Material: Tabs. I have encountered an issue with loading content on tabs after the initial one, where the functionality only works when the first tab is loaded. Below you can see the ta ...

The functionality of Angular 6 Material Nested Tree is disrupted when attempting to use dynamic data

In Angular 6, I am utilizing mat-tree along with mat-nested-tree-node. My objective is to dynamically load the data when the user toggles the expand icon. Attempting to apply the dynamic data concept from the Flat Tree example provided in Material Example ...

Angular Inner Class

As a newcomer to Angular, I have a question about creating nested classes in Angular similar to the .NET class structure. public class BaseResponse<T> { public T Data { get; set; } public int StatusCo ...

Utilizing TypeScript in Kendo UI for JQuery

I have implemented KendoUI for JQuery using TypeScript. Here is an excerpt from my "package.json" file: "dependencies": { "@progress/kendo-theme-material": "^3.19.2", "@progress/kendo-ui": "^2020.3.915 ...

Angular - passing information to a nested component

Within my application, I have a main component along with three sub-components. I am passing data to these three sub-components and using setTimeout to manage the timing of the data being sent. The first sub-component displays for 5000 milliseconds. The ...

What is the process for importing a map from an external JSON file?

I have a JSON file with the following configuration data: { "config1": { //this is like a map "a": [ "string1", "string2"], "b": [ "string1", "string2"] } } Previously, before transitioning to TypeScript, the code below worked: import ...

Yup will throw an error if both a minimum value is set and the field is also marked

I am attempting to validate my schema using yup: import * as yup from "yup"; let schema = yup.object().shape({ name: yup.string().min(5) }); const x = { name: "" }; // Check validity schema .validate(x, { abortEarly: false }) . ...

typescript import { node } from types

Exploring the possibilities with an electron application developed in typescript. The main focus is on finding the appropriate approach for importing an external module. Here is my typescript configuration: { "compilerOptions": { "target": "es6", ...

What is the correct way to bring in a utility in my playwright test when I am working with TypeScript?

I am working on a basic project using playwright and typescript. My goal is to implement a logger.ts file that will manage log files and log any logger.info messages in those files. To set up my project, I used the following commands and created a playwri ...

Using Typescript for the factory design pattern

My goal is to develop a factory for generating instances of MainType. To achieve this, I want to reuse existing types (specifically the same instance) which are stored in the ItemFactory. class BaseType { } class MainType extends BaseType { } class It ...

The superclass defines the type of the subclass

There is an abstract typescript class like this: abstract class Abstract { constructor (public parent?: Abstract) { } } Then, two subclasses are defined as follows: class Sub1 extends Abstract { } class Sub2 extends Abstract { } The issue aris ...

What is the best way to define the type of an object in TypeScript when passing it to a function

I am currently working on a function that accepts an object of keys with values that have specific types. The type for one field is determined by the type of another field in the same object. Here is the code: // Consider this Alpha type and echo function. ...

Encountering an issue with testing CKEditor in Jest

Testing my project configured with vite (Typescript) and using jest showed an error related to ckeditor. The error is displayed as follows: [![enter image description here][1]][1] The contents of package.json: { "name": "test-project" ...

Are ngFormModel characteristics subject to change?

I've been facing challenges while working with ngFormModel and dynamic properties from classes. Despite my efforts, I'm unable to update the ngFormModel when changing variables to reflect new values. You can see an example of this issue in the fo ...

Utilizing object as props in ReactJS with TypeScript

I'm new to working with ReactJS, and I made the decision to use typescript for my current project. The project is an application that fetches movies from an API and displays them. Take a look at the app: import React from 'react'; import &a ...

Undefined output in Typescript recursion function

When working with the recursion function in TypeScript/JavaScript, I have encountered a tricky situation involving the 'this' context. Even though I attempted to use arrow functions to avoid context changes, I found that it still did not work as ...