Closed
Description
TypeScript Version: 2.6.1-insiders.20171019 (via TS Playground)
Code
const addOne = (
effect: (
arg1: number,
arg2: () => 'A'
) => void
): void => {
effect(1, () => 'A');
};
addOne(
(
arg1: number,
arg2: (cheese: 'wheel') => void,
) => console.log(arg1 + 1)
);
Expected behavior:
Type error about arg2 mismatch, indicating that (cheese: 'wheel') => void is incompatible with () => 'A'.
Actual behavior:
No type error.
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
RyanCavanaugh commentedon Dec 7, 2017
See https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-functions-with-fewer-parameters-assignable-to-functions-that-take-more-parameters and the entry immediately following it
ghost commentedon Dec 7, 2017
Situations like these show why it's often a good idea to omit type annotations where possible. If you just write
addOne((arg1, arg2) => arg2(arg1))
you will get an error becausearg2
doesn't need any arguments.alexburner commentedon Dec 7, 2017
@RyanCavanaugh whoops, I should RTFM, those two sections address this exactly. I could understand the Substitutability argument for these cases, proving that nothing terrible will happen.
However, in our use case, it would still be preferable that a type error is thrown, since the mismatch of arguments reveals that a developer on our team is likely mis-using the tool. It would be nice if there was a compiler flag like
--strictFunctionSignatureMatching
that users could opt into for additional guard rails.@Andy-MS that's very interesting less explicit types add more strictness, I'm not sure I understand why that is. I've been assuming the more type annotations I add, the safer I am...
alexburner commentedon Dec 7, 2017
One issue I have with that FAQ description, it says:
But couldn't the forEach callback just use optional arguments?
ghost commentedon Dec 7, 2017
No, because marking a parameter as optional means it might not be provided. But
forEach
always provides those, so they are non-optional (and you can rely onindex
not beingundefined
).If you have
--noImplicitAny
enabled (part of--strict
), then we will tell you any time you need to add a type annotation. So you don't have to worry about some un-annotated thing beingany
.RyanCavanaugh commentedon Dec 7, 2017
See #17868 and others linked from that issue
RyanCavanaugh commentedon Dec 7, 2017
I've amended the FAQ since this is a common counter-question
alexburner commentedon Dec 7, 2017
Ohhhhhhhh @Andy-MS I see my misunderstanding, I was missing this:
And thanks @RyanCavanaugh for the link, I had been unable to search up a relevant issue. Your comment in there helps me understand:
Also @Andy-MS that makes sense about the
--noImplicitAny
flag meaning I can lean more heavily on type inference!