Philipp Sumi
Philipp Sumi

Reputation: 987

Typescript constraints not validated

Why do neither my TS linter nor compiler complain about the type massacre in my test method here? It appears that the item: T constraint isn't validated at all.

Tested on TS 3.8.3 and an old 3.2.2:

export class Foo {}

export class Bar {}

export class FooBar {
    test() {
        const thisIsNotABar: Bar = this.echo<Bar>(new Foo());
    }

    echo<T>(item: T): T {
        return item;
    }
}

Upvotes: 0

Views: 35

Answers (2)

jcalz
jcalz

Reputation: 327744

Ah, welcome to TypeScript's structural type system. In TypeScript, two types are the same if they have the same shape or structure. It does not depend on the name or declaration of the types, as in nominal type systems you might be more used to in other languages.

So, even though your Foo and Bar have different names and different declarations, they have the same shape and structure; namely that of an empty object type. And so, in TypeScript, Foo and Bar are exactly the same type.

If you want Foo and Bar to be considered distinct, you should add some incompatibility of structure, such as giving them different properties:

export class Foo {
    foo = ""
}

export class Bar {
    bar = ""
}

If you do that, the error you expected should happen:

    const thisIsNotABar: Bar = this.echo<Bar>(new Foo()); // error!
    // Foo is not assignable to Bar

Okay, hope that helps; good luck!

Playground link to code

Upvotes: 2

Mogzol
Mogzol

Reputation: 1405

This is because Foo and Bar are compatible (their definitions are identical). Try adding a property to one that isn't in the other and TypeScript should give you an error:

export class Foo { a: any }

export class Bar { b: any }

export class FooBar {
    test() {
        const thisIsNotABar: Bar = this.echo<Bar>(new Foo());
    }

    echo<T>(item: T): T {
        return item;
    }
}

Gives the error:

Argument of type 'Foo' is not assignable to parameter of type 'Bar'. Property 'b' is missing in type 'Foo' but required in type 'Bar'.

Upvotes: 2

Related Questions