I'm fairly new to TypeScript so I may well just be doing something stupid but I've found what appears to be either a bug or a limitation. I have defined an interface for a function that takes a Foo
. If I give that function to another function, the contract would seem to be that the function I pass must take any Foo
. However, if I define class Bar extends Foo
and then a function that takes a Bar
, but not a Foo
, I can pass that to a function that requires a function taking any Foo
. Example:
class Foo {
}
class Bar extends Foo {
}
interface TakesAnyFoo {
(x: Foo) : void;
}
function needsAFunctionThatTakesAnyFoo(f: TakesAnyFoo) {
let foo = new Foo();
f(foo);
}
function takesOnlyABar(x: Bar) {
console.log(`I got ${x}`);
}
needsAFunctionThatTakesAnyFoo(takesOnlyABar);
I think maybe what I need here is the equivalent of Java's lower bounded types. Something like:
interface TakesAnyFoo<T super Foo> {
(x: T) : void;
}
but Typescript doesn't appear to have this. How can I enforce a constraint that the function passed to needsAFunctionThatTakesAnyFoo
must accept any Foo
as its input?
Simplifying your code we have :
class Foo {
}
class Bar extends Foo {
}
function needsAFunctionThatTakesAnyFoo(f: (x: Foo) => void) {
let foo = new Foo();
f(foo);
}
needsAFunctionThatTakesAnyFoo((x: Bar) => { });
This is supported to allow the common pattern in event handlers. e.g. Giving a function that takes a MouseEvent
to an event specification that only supports Event
.
This is covered here: