Is there a way to automatically determine the parameters of a constructor to match the default class type in TypeScript

I need a function in a class that can utilize a type from constructor arguments, but I am unsure how to achieve this.

class CustomClass<Type1, Type2=any>{  
    a: string = 'a'
    constructor(private readonly parameters: { attributes: Type2 }) { }

    chooseType2(v: keyof Type2) { }

    chooseType1(t:keyof Type1){}
}

type Values={x:string,y:string}

// Here, I only want to specify the type for Type1, while Type2 is dynamically obtained from the parameters.
const customObject = new CustomClass<Values>({ attributes: { x:'1',y:'2',z:'3 '} }) 

customObject.chooseType1('x') // it should suggest x and y
customObject.chooseType2('x') //  it should suggest x, y, z


playground

Answer №1

If you need to utilize a generic function or create a generic class with multiple type parameters, the options are either to explicitly define all type arguments or allow the compiler to deduce them. TypeScript currently lacks support for partial inference of type arguments where only some are specified and others are inferred. A request has been made to address this limitation in future versions of the language, but as of now, it remains unchanged.


One approach is to specify the type that you prefer not to infer using the `typeof` type query operator:

const params = { a: '1', b: '2', c: '3 ' };
const foo = new Foo<Value1, typeof params>({ params });
// const foo: Foo<Value1, { a: string; b: string; c: string; }>

Another workaround involves currying the generic function at the type level, which adds an additional function call. For generic classes, a factory function may be required to achieve similar functionality.

You could implement this strategy in your example like so:

class _Foo<T1, T2>{
    a: string = 'a'
    constructor(private readonly config: { params: T2 }) { }
    selectT2(v: keyof T2) { }
    selectT1(t: keyof T1) { }
}
function Foo<T1>() {
    const Foo: new <T2>(config: { params: T2 }) => Foo<T1, T2> = _Foo;
    return Foo;
}
type Foo<T1, T2> = _Foo<T1, T2>;

Yet another workaround involves introducing a dummy parameter corresponding to the manually defined type, allowing the compiler to infer the type from the supplied dummy argument:

class Foo<T1, T2>{ 
    a: string = 'a'
    constructor(dummyT1: T1, private readonly config: { params: T2 }) { }
    selectT2(v: keyof T2) { }
    selectT1(t: keyof T1) { }
}

const foo = new Foo(
    null! as Value1, // Asserting the type
    { params: { a: '1', b: '2', c: '3 ' } }
);
// const foo: Foo<Value1, { a: string; b: string; c: string; }>

These workarounds present different ways to handle the lack of partial type argument inference in TypeScript. Each has its own set of trade-offs, and the choice depends on the specific requirements of your use case. Hopefully, future improvements to the language will provide more straightforward solutions for addressing this issue.

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

Transitioning an AngularJS factory to TypeScript

I'm currently in the process of transitioning an AngularJS application to Angular and one of the challenges I've encountered is converting my JavaScript code to TypeScript. While I've been successful with components and services, factories h ...

Tips on using constructor functions and the new keyword in Typescript

This is a demonstration taken from the MDN documentation showcasing the usage of the new keyword function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } const car1 = new Car('Eagle', 'Talon TSi&apos ...

Excluding certain source files in Typescript's tsconfig is a common practice to

My attempt to configure Typescript to exclude specific files during compilation is not working as expected. Despite setting exclusions in my tsconfig.json file, the code from one of the excluded files (subClassA.ts) is still being included in the compiled ...

What is the solution to the error message "Unable to assign property of undefined"?

I am currently working on an angular countdown timer and encountering a TypeError when attempting to access a variable from another component. I am struggling to identify the root cause of this issue. Here is the video tutorial that I am using as a referen ...

When a parameter is passed into a React-Query function with an undefined value, it can lead to the API returning a 404 error

Two parameters are sent from the frontend to trigger a GET request in another TypeScript file. It seems that one of the parameters is not successfully passed due to unknown rerenders, resulting in a 404 Error being returned by the API call in the console. ...

Creating hierarchical TreeNode structure in TypeScript

As I work with a flat one-dimensional array of type TreeNode (view interface definition below), my goal is to recursively traverse the array and add subsequent array elements as children. While attempting a non-recursive approach using a buffer, I encount ...

Invoke an ActionCreator within a different ActionCreator

Calling an ActionCreator from another file is proving to be a challenge... The products.ts file contains the ActionCreators and Reducers for Products... import { setStock } from './Store.ts'; //.... export const addProduct = (product: IProduct) ...

Discover the accurate `keyof` for a nested map in TypeScript

Here is the code snippet I'm working on: const functions={ top1: { f1: () => 'string', f2: (b: boolean, n: number) => 1 }, top2: { f3: (b: boolean) => b } } I am looking to define an apply f ...

I encountered an unexpected obstacle while reloading my Next.js application with animejs. The error message reads: "SyntaxError: Unexpected token 'export'." This unwelcome occurrence took place during the

Encountering an error with animejs when reloading my Next.js app: An unexpected token 'export' is causing a SyntaxError. This issue occurred during the page generation process. The error originates from file:///Users/.../node_modules/animejs/lib ...

Angular Tutorial: Understanding the Difference Between TypeScript's Colon and Equal To

I've been diving into the Angular4 tutorial examples to learn more about it. https://angular.io/docs/ts/latest/tutorial/toh-pt1.html One of the code snippets from the tutorial is as follows: import { Component } from '@angular/core'; @Co ...

Creating and updating a TypeScript definition file for my React component library built with TypeScript

As I work on developing a React library using TypeScript, it is important to me that consumers of the library have access to a TypeScript definition file. How can I ensure that the TypeScript definition file always accurately reflects and matches the Java ...

Using a Javascript library within an Angular component: A comprehensive guide

I've been working on a Web-Client project that involves visualizing sensor data such as velocity and acceleration within a coordinate system. In order to display this coordinate system, I decided to use the graph.js library from https://github.com/dhu ...

What are the steps to correct a missing property in an established type?

Currently, I am in the process of converting an existing Node.js + express application from plain JS to TypeScript. Although I understand why I am encountering this error, I am unsure about the correct approach to resolve it. The type "Request" is coming f ...

Utilizing Foundation and jQuery in a Next.js web development project

I've been attempting to incorporate Zurb Foundation's scripts into my next js application, but I keep encountering an error message when trying to include the Foundation core. The error I'm seeing is: /Users/alasdair_macrae/Sites/merlin/spa_ ...

An issue has been identified with React's HTML input maxLength feature where it does not display an error

Within my form, I have an input field that currently does not include validation for a maximum length. <input type="text" className="form-control" id="company" onBlur= ...

Google Chrome does not support inlined sources when it comes to source maps

Greetings to all who venture across the vast expanse of the internet! I am currently delving into the realm of typescript-code and transcending it into javascript. With the utilization of both --inlineSourceMap and --inlineSources flags, I have observed t ...

I rely on the angular-responsive-carousel library for my project, but unfortunately, I am unable to customize the arrow and dots

When it comes to CSS, I utilize ng deep style in Angular 10 to make changes for browser CSS. However, I am facing an issue where the problem is not being resolved by my CSS code. Here is a snippet of my code: > ::ngdeep .carousel-arrow { > b ...

What are some ways to incorporate advanced/nested type variables when using arrow functions?

Is there a way to use "advanced/nested" type variables, similar to how T is utilized in this function declaration, when working with arrow functions? function wrapInObject<T>(key: string) { return (x: T) => ({ [key]: x }); } I attempted to ach ...

How to start Angular2 prototype with an object literal

export abstract class GridColumn { public field?: string; public sortField?: string; public header?: string; public footer?: string; public sortable?: any = true; public editable?: boolean = false; public filter?: boolean = true ...

How can I generate pure JavaScript, without using Typescript modules?

Take this scenario as an example ... index.ts import { x } from "./other-funcs"; function y() { alert("test"); } x(y); other-funcs.ts import { z } from "some-module"; export function x(callback: () => void): void { z(); callback(); } ...