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