Erik Moldtmann
Erik Moldtmann

Reputation: 164

Typescript generic type check not working as expected

I have made a simple test fixture:

export interface ITest1 {}
export interface ITest2 {}
export interface ITestGeneric<T> {}

export function test() {
  let p: ITestGeneric<ITest1> = {}
  let q: ITestGeneric<ITest2> = p;
}

I would expect the last line to fail, because in C# such incompatible type assignments don't work. However, typescript compiles this without complaint.

Can someone tell me why this works and what I have to do to make this fail?

Upvotes: 2

Views: 2750

Answers (3)

Erik Moldtmann
Erik Moldtmann

Reputation: 164

Thanks to @Titian Cernicova-Dragomir's advice I made a working solution.

To make a type distinctive, just add property that equals the type's name:

export interface ITest1 { test1: any }
export interface ITest2 { test2: any }

The type of the property doesn't matter as far as I've tested. Typescript seems to only look for the property's name, and if that is different, the type is different.

When instantiating the type just set the property to anything, an empty object or an empty string, it doesn't really matter.

let p: ITest1 = { test1: {}};

Upvotes: 0

David Lebee
David Lebee

Reputation: 596

I think since you don't restrict the

ITestGeneric <T>

it allows it. If you did

ITestGeneric<T extends ITest1>

It would be more restrictive.

TypeScript generics are not CSharp generics and are not 100% the same.

your interface just says it has to be a ITestGeneric of anything.

Upvotes: 0

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 250396

This is because typescript uses structural compatibility to determine if two types are compatible. In your case since ITestGeneric has no members, it is basically compatible with anything. If you start adding properties, incompatibilities will quickly appear:

export interface ITest1 { t1: string}
export interface ITest2 { t2: number}
export interface ITestGeneric<T> { value: T}

export function test() {
    let p: ITestGeneric<ITest1> = {} // error
    let q: ITestGeneric<ITest2> = p; // error
}

You can read more about type compatibility in typescript here

Upvotes: 6

Related Questions