Unexpectedly, TypeScript generic class fails to produce the desired type error

Exploring the use of generic classes in TypeScript has led me to a roadblock - I can't seem to generate the specific type error I'm aiming for when an incorrect argument is passed to a function. I've attempted several different approaches, but none of them seem to work when using objects as generic type arguments. The issue only arises with more basic types like strings and booleans.

Try it out here

class Test<T> {
    func1(_other: Test<T>) : void {}
    func2(_other: T) : void {}
    func3<U extends Test<T>>(_other: U) : void {}
    func4<U extends T>(_other: U) : void {}
}

// CRTP
class A extends Test<A> {}
class B extends Test<B> {}

// without CRTP, object type
class G {}
class X extends Test<G> {}

// without CRTP, basic type
class Y extends Test<boolean> {}

const a = new A();
const b = new B();
const x = new X();
const y = new Y();

// No type errors encountered here. Why?
a.func1(b); a.func2(b); a.func3(b); a.func4(b);
a.func1(x); a.func2(x); a.func3(x); a.func4(x);

// However, all four functions produce type errors as expected
a.func1(y); a.func2(y); a.func3(y); a.func4(y);

Answer №1

In Typescript, the distinction is structural rather than nominal.

What this means is that if two types have the same structure, they are considered the same type. The specific name or instance of the type is not important.

For example, consider these two types as being equivalent:

class A extends Test<A> {}
class B extends Test<B> {}
const a: A = new B() // no error

However, if there are variations in the shapes of the classes, you will encounter expected errors:

class A extends Test<A> { a = 'string' }
class B extends Test<B> { b = 123 }
const a: A = new B() // type error
// Property 'a' is missing in type 'B' but required in type 'A'.(2741)

As a result, once properties are introduced to these classes, errors will become apparent.

Check out playground for more details

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

Exploring the Angular Structure: Utilizing External Libraries in Feature Modules

Currently, I am in the process of building a new angular application that includes various feature modules. As part of this project, I am integrating Material Design components. I am seeking advice on the best approach for importing Material Design modules ...

Embedding a TypeScript React component within another one

Currently, I'm facing an issue with nesting a TypeScript React component within another one, as it's causing type errors. The problem seems to be that all props need to be added to the parent interface? Is there a way to handle this situation wi ...

What is the rationale behind allowing conflicting types in intersection types?

When presented with two interfaces containing conflicting member types: interface A { x: number } interface B { x: string } It becomes impossible to create an interface that extends both: interface I extends A, B // error TS2320: Interface 'I' ...

Attempting to eliminate any dates that have already occurred

I am faced with an array containing various dates in string format such as "2016-08-12". My goal is to eliminate any dates that have already passed by comparing them to today's date. I am using TypeScript for this task. Here is a snippet of my datoAr ...

Tips for retrieving a child component's content children in Angular 2

Having an issue with Angular 2. The Main component displays the menu, and it has a child component called Tabs. This Tabs component dynamically adds Tab components when menu items are clicked in the Main component. Using @ContentChildren in the Tabs comp ...

Error encountered on login page: The protocol 'http' does not exist (related to HTML, TypeScript, Angular2, and JavaScript)

Screenshot of the issue: Access the complete project here: Link to a Plunker example of a log-in screen: http://plnkr.co/edit/j69yu9cSIQRL2GJZFCd1?p=preview (The username and password for this example are both set as "test") Snippet with the error in ...

What causes an array to accumulate duplicate objects when they are added in a loop?

I am currently developing a calendar application using ExpressJS and TypeScript. Within this project, I have implemented a function that manages recurring events and returns an array of events for a specific month upon request. let response: TEventResponse ...

"Patience is key when waiting for a response from an Angular

I've come across several similar posts with the same title, but none of them address my specific use case. In my situation, I have an array of items with properties that can be ('serials','macs','null'). For each type o ...

Avoid the auto-generated modifications in valueChanges for FormControl

Currently, I have a registration form for events where users are required to input the date, time, and recurrence frequency (daily, weekly, monthly, or none). Additionally, there is an option for users to specify when they want the recurrence to end. Howev ...

I can't seem to figure out why this error message keeps popping up: "No declaration file found for the module 'swagger-jsdoc'"

Here are the results of my installation: success Saved 19 new dependencies. info Direct dependencies ├─ <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ddbfbeafa4ada99de8f3edf3ec">[email protected]</a> ... (oth ...

Having trouble getting the onClick function to work in your Next.js/React component?

Recently, I delved into using next-auth for the first time and encountered an issue where my login and logout buttons' onClick functions stopped working when I resumed work on my project the next day. Strangely, nothing is being logged to the console. ...

Is there a method to run code in the parent class right after the child constructor is called in two ES6 Parent-Child classes?

For instance: class Parent { constructor() {} } class Child { constructor() { super(); someChildCode(); } } I need to run some additional code after the execution of someChildCode(). Although I could insert it directly there, the requirement is not to ...

Ensure that a particular key type is determined by the value of another key within the object (Utilizing Discriminated Unions)

The title of my question may not have been clear about what I am looking for, but what I need is something known as discriminated unions. You can find more information about it here: https://www.typescriptlang.org/docs/handbook/unions-and-intersections.htm ...

Utilizing the Where clause to define distinct generic types

I am currently in the process of creating a bijective dictionary class, with a specific requirement to ensure that the two generic types are not identical for a couple of important reasons. Firstly, my goal is to have it adhere to the IDictionary interfac ...

A comprehensive guide on extracting data from the query string in Angular

There is a specific query string format that we need to handle. The input parameter of the method comes in the form of a string and it's not an instance of ActivatedRoute. http://localhost:4200/users?param1=en&param2=nk I've attempted to rea ...

Is there a way for me to implement a service method that retrieves the onSnapshot result, allowing me to seamlessly integrate it into my Component or Ionic Page?

Currently, I am using "ionic-angular": "3.7.1" along with Firebase Cloud Firestore. My goal is to retrieve all the documents from the Post collection whenever they are updated, deleted, or added. I have been informed that by calling the onSnapshot Method, ...

Safari problem with decoding audio data in AudioContext

I am attempting to convert .ogg data into an ArrayBuffer. In my Angular application component, I have the following code snippet: ngOnInit() { (window as any).AudioContext = (window as any).AudioContext || (window as any).webkitAudioContext; this.aud ...

Creating a number of arrays based on the row of a .CSV file can be accomplished in Angular by utilizing the

Implementing an Angular template to read .CSV files and generate a table involves creating two separate files: one for the header and another for the table content. For the header CSV file: header.csv https://i.stack.imgur.com/ojMo6.png For the table da ...

Issue with React Router: Attempting to assign an unsafe `any` value

I have successfully used this code in my previous projects. However, I am puzzled as to why typescript is throwing this particular error: Unsafe assignment of an `any` value.eslint@typescript-eslint/no-unsafe-assignment Unsafe call of an `any` typed value. ...

Update the datalist in the view once the user has completed typing in the textbox using Angular 7

Struggling to automatically refresh a datalist in the view once the user finishes typing in the textbox and updates the results. I've experimented with angular directives, Observable, timeouts, and debounces without success. It seems like I've ex ...