What allows us to create an instance of a generic class even without defining the generic type parameter?

It is intriguing how TypeScript allows the instantiation of a generic class without specifying the actual generic type parameter. For instance, in the code snippet below, the class Foo includes a generic type parameter T. However, when creating a new Foo instance with const foo = new Foo(), there is no requirement to specify the generic type parameter. Thus, foo is of type Foo<unknown> and bar is of type valueType<unknown>.

Why does TypeScript allow this behavior without throwing an error? What practical application does it serve? Is there a way to enforce TypeScript to mandate the inclusion of a generic type parameter?

type valueType<T> = {
   name: string,
   key: T|null,
};

class Foo<T> {
   private value: valueType<T>;

   public constructor() {
      this.value = {
         name: '',
         key: null,
      };
   }

   public setValue(value: valueType<T>) {
      this.value = value;
   }

   public getValue(): valueType<T> {
      return this.value;
   }
}

const foo = new Foo();
const bar = foo.getValue();

Typescript Playground Link

Answer ā„–1

In similar discussions on Stack Overflow, it has been suggested as a viable approach to default to the never type when dealing with generic parameters. While this may seem like a reasonable choice at first glance, it poses the risk of causing issues down the road. The never type is essentially useless and using it will prompt users of your class to realize their mistake and provide a type argument to Foo.

type valueType<T> = {
   name: string,
   key: T|null,
};

class Foo<T = never> {
   private value: valueType<T>;

   public constructor() {
      this.value = {
         name: '',
         key: null,
      };
   }

   public setValue(value: valueType<T>) {
      this.value = value;
   }

   public getValue(): valueType<T> {
      return this.value;
   }
}

const foo = new Foo();
// bar will now have the `never` type, making it unusable
const bar = foo.getValue();

Answer ā„–2

Why does TypeScript allow instantiation of a generic class without specifying the actual generic type parameter?

Typically, the generic type can be inferred from the arguments provided. However, if there are no arguments, the type must be explicitly set or it defaults to unknown.

For example, if we update the constructor to take a key of type T as an argument:

public constructor(key: T) {

TypeScript will automatically assign the generic variable based on the type of the key argument passed to the constructor. This eliminates the need to specify the type when creating an instance like new Foo<string>('x'). Simply using new Foo('x') will result in a Foo<string>.

Can TypeScript be configured to require a generic type parameter?

It is unlikely but possible through your tsconfig or linter settings.

Making every generic function or class declare an explicit type parameter could be burdensome. Type inference plays a crucial role in TypeScript, and explicit types are only necessary when inference would default to unknown.

Many generic functions and classes set a default value for the generic type to use when inference is not possible. While unknown poses challenges, using any is a viable alternative (although not ideal). To set any as a default, you can do the following:

class Foo<T = any> {

Now, calling new Foo() will result in a Foo<any>.

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

Utilizing Async/Await to Streamline Google Maps Elevation Requests

I'm struggling to run this in a sequential manner. I've experimented with various methods like using Promise.all and getting stuck in callback hell, but what I really need is to obtain elevations for each point that has a valid altitude value (no ...

Issue arises when trying to implement sidebar navigation in Angular with Materialize CSS

Just starting my Angular journey and running into some trouble trying to set up a practical and responsive menu using SidebarNav and Dropdown. I used CLI to install and configure angular2-materialize and materialize-css. To create the menu, I made a comp ...

Struggling to properly implement background images in a React application using Tailwind CSS

I'm currently developing a React application using Tailwind CSS for styling. In my project, I have an array of items called "trending," and I'm attempting to iterate through them to generate a series of divs with background images. However, I am ...

I've been stuck for hours, is there anything I should include?

I'm attempting to access http://localhost:4200/Personnes/view/:2, but I encountered the following error (ERROR TypeError: Cannot read property 'nom' of undefined) "My personnnes.service.component.ts" `export class PersonnesService { baseUr ...

Validate the button's status in Ionic

When I click on a button, I am trying to retrieve the Toggle state immediately. However, I consistently receive a value of true, even when my toggle is actually set to false. I believe the issue lies in how I am manipulating the DOM. Here is an example ...

Incorporating node packages into your typescript projects

I have been exploring various discussions on this forum but I am still unable to make it work. My goal is to compile the following code in TypeScript. The code is sourced from a single JavaScript file, however, due to issues with module inclusion, I am foc ...

The object's value may be 'undefined' after utilizing a switch case to ensure it is not undefined

Before I encountered the error Object is possibly 'undefined'.ts(2532) at testObject["x"], I had used case "x" in testObject. Why did this happen? Should I create my own type guard for it? interface TestObject { a?: number; ...

What are the distinctions between using getStaticPaths + getStaticProps and useRouter in NextJS?

I'm currently diving into the world of NextJS and finding myself puzzled by the distinctions between getStaticProps & getStaticPaths compared to utilizing useRouter().query. At this point, it appears to me that both methods serve a similar purpos ...

Issue with debounce function failure in handling onChange event for a controlled input field

Currently, I am experimenting with the Material UI React framework. I recently moved my application to Material UI using TypeScript. However, I seem to be encountering an issue with the debounce function when used in the onChange handler for input fields. ...

How can I create an interceptor in Angular2 to detect 500 and 404 errors in my app.ts file?

Creating an Angular2 Interceptor for Handling 500 and 404 Errors in app.ts In my app.ts file, I am looking to implement an interceptor that can detect a 500 or 404 error so that I can appropriately redirect to my HTML 404 or HTML 500 pages. Is this funct ...

Utilizing various filters and sorting options on API response within Angular 8

Upon receiving the following API response: [ { "imgPaths":[ "gallery/products/55ccb60cddb4d9bded02accb26827ce4" ], "_id":"5f3e961d65c6d591ba04f3d3", "productName":" ...

Guide to creating an Express + TypeScript API using an OpenAPI 3.0 specification

After creating specifications for my REST API server using OpenAPI 3.0, I found myself wanting to generate an expressjs app quickly instead of manually writing repetitive code. However, the generated code from editor.swagger.io is in javascript, which does ...

Jest test encounters an error due to an unexpected token, looking for a semicolon

I've been working on a Node project that utilizes Typescript and Jest. Here's the current project structure I have: https://i.stack.imgur.com/TFgdQ.png Along with this tsconfig.json file "compilerOptions": { "target": "ES2017", "modu ...

What is the process for implementing an abstract factory pattern in Typescript?

Iā€™m currently facing a challenge while attempting to incorporate a standard abstract factory pattern in Typescript, only to find that the compiler is not quite on board with my efforts. Below is a simplified version of the code I am working with: abstra ...

Mapping intricate entities to intricate DTOs using NestJS and TypeORM

Currently, I am using the class-transformer's plainToClass(entity, DTO) function to transform entities into DTO objects. In addition, I have implemented the transform.interceptor pattern as outlined in this source. I make use of @Expose() on propert ...

Common mistakes made while working with decorators in Visual Studio Code

Having trouble compiling TypeScript to JavaScript when using decorators. A persistent error message I encounter is: app.ts:11:7 - error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the ' ...

Unusual class title following npm packaging

Currently, I am working on developing a Vue 3 library with TypeScript. We are using Rollup for bundling the library. Everything works as expected within the library itself. However, after packing and installing it in another application, we noticed that th ...

Error message: NextJs throws aReferenceError when trying to access the document object on page refresh

encountered the error ReferenceError: document is not defined when attempting to refresh the page I am working on creating a component using react-quill and then calling that component within a page. This is my component : import React, { useState } from ...

RXJS expand keeps on recursing indefinitely

After successfully uploading a file to Firebase, I implemented a recursive function to listen for GCP trigger logs. Everything seems to be working well, but I'm facing an issue where the recursive expand function never exits. Despite checking the val ...

Issue with playing audio file using HowlerJS

Having trouble playing a .mp3 file in my project directory with Howler. I'm not sure if there's an error in my src. When I tried playing an online hosted audio file, it worked fine. I've placed the audio file in the same directory as Slideon ...