Why is this code allowed in TS?
interface IFoo {
foo(a: string | number): void
}
class Bar implements IFoo {
foo(a: string) { }
}
I think the compiler should throw error, as param a: string of Bar is narrower/not substitutable to a: string | number of IFoo.
This is deliberate design and intended behavior due to Function Parameter Bivariance.
https://www.typescriptlang.org/docs/handbook/type-compatibility.html#function-parameter-bivariance
Essentially, this means that function types are checked in both ways. The class implementation of
foois not only assignable to the declaration inIFooif its type is more narrow but also if it's wider. A type error only occurs if neither the interface declaration nor the class type implementation are assignable to one another.You can prevent this by enabling
--strictFunctionTypes. However, there is another important thing to notice. The strict parameter type checking only works when declaringfooas an arrow function (foo: (a: string | number) => void;).https://www.typescriptlang.org/tsconfig/#strictFunctionTypes
Now you get your expected parameter type checking: