Closed
Description
TypeScript Version: 2.9.0-dev.20180503
Search Terms: overload, function, parameter, return
Code
function funct5(param1: boolean): string;
function funct5(param1: Date): number;
function funct5(param1: boolean | Date): string | number {
if (typeof param1 === "boolean") {
return 1; // Expected to have a TS error saying that only a string is valid
} else {
return 0;
}
}
Expected behavior:
Since the param1 is narrowed down to be a boolean, only a single overload is valid (the first one that returns a string). However, I can return a number which should only be valid if the param1 is a Date.
Actual behavior:
I was expecting TypeScript to notify me that the return type was invalid because of the type of the param1.
Playground Link: Link
Related Issues:
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
ghost commentedon May 3, 2018
Implementation of overloads is unsafe -- only the version of the function with a body is actually checked. So it's checked as if you didn't write the overloads above it, but called as if you had only written the overload signatures.
jcalz commentedon May 3, 2018
Disclaimer: I am not a TypeScript language designer/maintainer.
This is intended behavior, although it might not be completely clear from the handbook documentation or the spec, and doesn't seem to be directly addressed in the FAQ.
The stuff you probably know: for overloaded functions there are one or more overload signatures (the ones that have no implementation after it), and a single implementation signature (the one with the implementation after it). The implementation signature is required to be at least as general as all the overload signatures (or, from the other direction, each overload signature must be at least as specific as the implementation signature).
What you might not realize: The overload signatures only constrain what the caller of the function can do, while the implementation signature only constrains what the implementation of the function can do. The caller doesn't see the implementation signature, and the implementation doesn't see the overload signatures.
So in your case the compiler doesn't complain that the return value for a
boolean
input is anumber
, since the return type of the implementation signature isstring | number
, andnumber
is compatible withstring | number
. Only the overload signatures care about theboolean
-in-string
-out constraint, which means only the function caller will expect this. As you have discovered, this is not fully type-safe. I imagine that this was chosen for practical reasons (limits the work that the type checker needs to perform while still giving some semblance of type safety) but I can't speak authoritatively on that.Hope that makes sense.
Related issues: #22609
MrDesjardins commentedon May 3, 2018
Thank you both of you.
I understand the challenge with more complex overloading scenario which TypeScript may have a hard time to analyze every situation, but it seems rational to believe that as a developer if I provide the type for a specific disposition of type that not only the consumer is leveraging that typing but also the maintainer of the function. The actual state of overloading is precarious leaving the doubt that we have safety mechanism because we are explicit when in fact an error can slip easily. Stil, better than nothing because the consumer of the library is getting an additional value than just the union parameters and returns.
Thank you for finding the related issue. I couldn't see it myself. Hopefully, something will improve around that feature.
typescript-bot commentedon May 18, 2018
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.