Obtain the type parameter in Typescript

In my code, I have created a simple IFactory<OUT> interface along with two classes that implement it.

export interface IFactory<OUT = any> {
    create(): OUT;
}

// number implementation
export class NumberFactory implements IFactory<number> { ... }

// string implementation
export class StringFactory implements IFactory<string> { ... }

In addition to this, there is a method called calculate() which constructs an object based on the specified model.

Here is an example of a model:

const model: Record<string, IFactory> = {
    num: new NumberFactory(),
    str: new StringFactory()
}

After calling the calculate() method, the result will look something like this:


const result = calculate(model);

/// result
/// {
///    num: 1,
///    str: "str"
/// }

The main question here is how we can determine the type of the result. I have attempted to use TypeScript utilities but haven't been successful so far.

Your assistance in solving this issue would be greatly appreciated. Thank you!

Answer №1

If you define the type of model as Record<string, IFactory>, it may lead to limitations. This would cause the compiler to treat model as a generic object with any possible keys and values of IFactory. While this can be useful for dynamic property management in model, it may not always be ideal. It's usually better to let the compiler infer the type of model for you:

const model = {
   num: new NumberFactory(),
   str: new StringFactory()
}

/* const model: {
    num: NumberFactory;
    str: StringFactory;
} */

By doing this, you increase the chances of having calculate() accurately handle input types and produce expected outputs. Here is one possible way to implement this functionality:

function calculate<T extends object>(model: { [K in keyof T]: IFactory<T[K]> }) {
   return Object.fromEntries(
      Object.entries(
         model as Record<string, IFactory>
      ).map(([k, v]) => [k, v.create()])
   ) as T;
}

In this implementation, I use inference from mapped types to specify the output of calculate() as an object type T, with input properties wrapped in IFactory to produce IFactory<T[K]>.

The compiler may not fully validate this process within the function body, so I utilize type assertions to ensure proper handling. The responsibility of maintaining type safety then falls on me.

Let's test this out:

const result = calculate(model);
// const result: {
//    num: number;
//    str: string;
// }

console.log(result);
/// result
/// {
///    num: 1,
///    str: "str"
/// }

The results show that calculate() successfully uses model and infers T as {num: number; str: string;}, working correctly at runtime too.

Playground link to code

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

The return type is not undefined but the switch covers all possibilities

I'm struggling to understand the issue with this simple example interface List { "A": false, "B": false, } // The function is missing a return statement and its return type does not include 'undefined'.ts(2366) / ...

Traverse through an array of objects with unspecified length and undefined key names

Consider the following object arrays: 1. [{id:'1', code:'somecode', desc:'this is the description'}, {...}, {...}] 2. [{fname:'name', lname:'last name', address:'my address', email:'<a h ...

Utilize Array.push to add 2 new rows to a table using Angular 4

I have two arrays that are almost identical, except for two items which are the fakeDates: this.prodotti.push({ idAgreement: this.idAgreement,landingStatus: this.landingStatus, landingType: this.landingType, startDate: this.startDate, expirationDate: thi ...

Could adjusting the 'lib' compiler option to incorporate 'dom' potentially resolve TS error code TS2584?

My preferred development environment is Visual Studio where I write Typescript code. I am facing an issue where I simply want to use the command "document.write" without encountering an error. Unlike my previous PC and VS setup, I am now getting an error ...

Improving the structure of a TypeScript switch statement

Looking for a more efficient way to implement a switch statement in TypeScript? Here is the current code snippet from a component: switch (actionType) { case Type.Cancel { this.cancel(); break; } case Type.Discard { thi ...

Create a versatile generic object using TypeScript

Looking to create a versatile onFilterChange helper function that works for all filters, eliminating the need to write it out separately each time. However, I've hit a snag: // helper.ts export function onFilterChange(prevState: Record<string, any& ...

Unable to create a loop within the constructor to assign API values

I created an export type shown below: export type Program{ key: string; value: string; } An array of values is returned from the API like this: apival = ["abc", "xyz" ...etc] In my component's constructor, I am implementing the f ...

Create an alternate name for a specific type of key within a nested record

There are three simple types available: const structureTypes = z.enum(["atom","molecule"]) const atomTypes = z.enum(["oxygen","hydrogen"]) const moleculeTypes = z.enum(["water","ammonia"]) The goal is to define a type for a cache where the keys correspond ...

Enhance User Experience - Automatically highlight the first element in Prime NG Menu when activated

I have been working on transitioning the focus from the PrimeNG menu to the first element in the list when the menu is toggled. Here is what I've come up with: In my template, I added: <p-menu appendTo="body" #menu [popup]="true&quo ...

Exploring the power of Javascript for number lookup

I am currently working on a coding project using TypeScript and JavaScript to locate a specific number provided by the user within a list. The goal is to display whether or not the number is present in the list when the 'search' button is pressed ...

Versatile Typescript options

Is it possible to enforce a value to be within a list using TypeScript with enums? Can this be achieved with TypeScript type definitions? enum Friend { JOHN, SALLY, PAUL, } type MyFriends = { friends: Friend[], bestFriend: <> //How ca ...

Exploring the concept of union return types in TypeScript

Hello, I am facing an issue while trying to incorporate TypeScript in a way that may not be its intended use. I have created a custom hook called useGet in React which can return one of the following types: type Response<T> = [T, false, false] | [nul ...

Utilize dynamic components to load varying data sets multiple times

Is there a way to dynamically load a component multiple times and pass data based on certain values so that it will display with real-time information? I came across an example at the following link: In this example, there is a messageComponent with a "m ...

Using an early return statement in Typescript triggers the Eslint error "no useless return"

Could you please provide some feedback on the Typescript function I have written below? The function is meant to check for validation, and if it fails, exit out of the submit function. However, ESLint is flagging a 'no-useless-return' error. I&ap ...

Understanding the fundamentals of TypeScript annotation and node package management

As a newcomer to Typescript, I have grasped the basics but find myself becoming a bit bewildered when it comes to best practices for handling node packages, annotations, and defining types within those packages in my projects. Do I really need to annotate ...

What is causing the error message "Module '@reduxjs/toolkit' or its type declarations are not found" to appear?

Although I have a good understanding of React-Redux, I decided to delve into TypeScript for further practice. Following the recommended approach from the react-redux team, I created a new project using the TS template: "npx degit reduxjs/redux-templa ...

Obtain data from a single module and incorporate it into a different one

In my Angular 2 application, I am dealing with two component files - home.ts and folder-selector.ts. Within the folder-selector.ts file, there is a variable named pathToNode. I am trying to figure out how to access this value from within the home.ts file ...

When selecting a MenuItem, only a ReactOwner has the ability to add a ref using addComponentAsRefTo(...)

I'm currently working on a basic component that looks like this: class App extends React.Component<{}, {}> { constructor() { super(); } render() { return ( <MuiThemeProvider muiTheme={muiTheme}> <div> ...

Issue encountered while deploying Next.js application on vercel using the replaceAll function

Encountering an error during deployment of a next.js app to Vercel, although local builds are functioning normally. The issue seems to be related to the [replaceAll][1] function The error message received is as follows: Error occurred prerendering page &q ...

Tips for optimizing the performance of nested for loops

I wrote a for loop that iterates over 2 enums, sending them both to the server, receiving a value in return, and then calculating another value using a nested for loop. I believe there is room for improvement in this code snippet: const paths = []; for awa ...