Can someone please explain, why in this code the assignment to the constant of type InterfaceA works, but the assignment to the constant of type InterfaceB throws an error:
interface InterfaceA {
doSomething (data: object): boolean;
}
interface InterfaceB {
doSomething: (data: object) => boolean;
}
function doIt (data: { type: string; }): boolean {
return true;
}
const A: InterfaceA = {
doSomething: doIt
};
const B: InterfaceB = {
doSomething: doIt
};
To me, both interfaces are defining the same, only the notation is different.
If this is not a bug in TypeScript, and there is a real reason, then let's come to my second question: I need to specify, that "doSomething" is optional and can either be a function, or a RegExp:
interface InterfaceB {
doSomething?: ((data: object) => boolean) | RegExp;
}
How could I achieve this, with the notation of InterfaceA?
1.) There is a difference between method and function property declaration:
2.) TypeScript 2.6 introduces a compiler flag for stronger-typed, sound function types:
So in general that is a good thing. In your example,
InterfaceB
has following contract: "Every function that can deal with a generalobject
is compatible". But you want to assign a functiondoIt
, that expects specific objects of type{ type: string; }
as input. A client that usesInterfaceB
thinks, it is enough to passobject
, but the implementationdoIt
wants something more concrete, so you rightfully get that error.And why doesn't the error happen with
InterfaceA
?In contrast, methods like
doIt
inInterfaceA
are excluded from--strictFunctionTypes
for practical reasons. The developers decided the type system to be not too pendantic with built-in methods ofArray
etc. to have a reasonable balance between correctness and productivity.So, in favor of stronger types, I would prefer the following type, which works for your case (sample):