-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Infer overload signatures from implementation bodies #10765
Comments
Happy to be pointed to an existing discussion/issue/explanation since this has surely come up before. I did try searching in earnest but didn't notice anything. I would have hoped to be able to implement: type S = 'a' | 'b';
function f(s: 'a'): string {
return 'a';
}
function f(s: 'b'): number {
return 2;
}
// Perhaps with a necessity for:
function f(s: S): never {
throw new Exception("this can't happen");
} Which allows all the functions to typecheck as units and has enough information to emit as a switch statement, but I imagine this is either stylistically inappropriate or doesn't work in all cases? |
Function overloads are only related on signatures. The idea is that we trust the implementation signature as written. It's up to the user to deliver on the contract of each overload. It's not obvious how we'd relate the implementation signature and the implementation body for every overload. It seems pretty non-trivial, even with our control flow analysis. |
I see - thanks for responding. :) Just to throw one proposal out there, I'd be curious to hear your comments on allowing overloading in the manner of my second comment here - that certainly provides a fairly clear cut path to relate the implementation and body. I understand that there's definitely room for complexity around duplicate implementation bodies (I don't believe that's possible at all right now), but is there any chance that could work? To add some context, I'm proposing that the syntax as specified there would compile to this singular implementation body: function f(s: 'a' | 'b'): string | number {
switch (s) {
case 'a':
return 'a';
case 'b':
return 2;
}
} In the case of string literal overloading (and tagged unions, as below), this seems to be completely possible to generate and for the implementation functions to be typechecked. Relatedly, it would then be possible to provide overloading resembling that of other languages for tagged union members: interface Cartesian {
kind: 'cartesian';
x: number;
y: number;
}
interface Polar {
kind: 'polar';
r: number;
theta: number;
}
type Coords = Cartesian | Polar;
function distance(c: Cartesian): number {
return Math.sqrt(c.x*c.x + c.y*c.y);
}
function distance(p: Polar): number {
return p.r;
}
// Again I'm including this because I don't know a good way to indicate the common parent type.
function distance(co: Coords): never {} Which compiles to a switch statement as above, makes it easy to associate body and return type in solving the problem raised in this issue and reads clearly, resembling conventional overloading in many other languages. (I'm aware this is a lot more than this issue started out accounting for - as this morphs towards suggestion I'm happy to move this elsewhere, if it gets to the point of being entertained.) |
Thanks for pointing me to that. I'll see if I can put together a proposal that doesn't trip any alarm bells, perhaps. What I propose above is dramatically simpler than that the general cases shot down in the thread and has no non-explicit RTTI or overhead. Certainly in (say) Scala, some behaviour can only act on sealed traits, so a heavily restricted form of that proposal that gives many of the benefits without tripping not-pretty-code (4) and potentially the other two concerns might be possible (only allowing overloading on string literal types and tagged unions, say). :) Given that without a fleshed out proposal the behaviour I highlighted in my opening post here is considered 'known', should this thread be closed? |
I just noticed the title change that you made. I'll look into writing a thorough proposal in line with the guidelines and TypeScript's core set of language rules/intentions and bring it back to this thread. |
There's at least a few duplicates out there, but the TL;DR is that we've decided to not implement this functionality. |
TypeScript Version: nightly (2.1.0-dev.20160906)
Code
Expected behavior: fails typechecking f(s: 'b') is annotated as returning a number, but returns a string in the implementation.
Actual behavior: typechecks successfully
I understand that the lattermost function in each case should typecheck as an isolated unit, only I would have hoped that this could be checked or at least warned about.
Given that we can throw an error in the below example, I think it should be possible to typecheck the above examples:
Edit: tsconfig.json is
{ "compilerOptions": { "strictNullChecks": true, "noImplicitAny": true } }
The text was updated successfully, but these errors were encountered: