Skip to content
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

Overloading with/without arguments throws a compiler error #5658

Closed
Izhaki opened this issue Nov 13, 2015 · 10 comments
Closed

Overloading with/without arguments throws a compiler error #5658

Izhaki opened this issue Nov 13, 2015 · 10 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@Izhaki
Copy link

Izhaki commented Nov 13, 2015

Given the following code:

restoreState() {
    var iLastState = this.stateStack[ stateStack.length - 1 ];
    this.restoreState( iLastState );
}

restoreState( aState: TransformerState ) {
    this.state = aState
}

And the following call:

popState() {
    var iState = this.stateStack.pop();
    this.restoreState( iState ); // Error on this line
}

The compiler complains:

error TS2346: Supplied parameters do not match any signature of call target.

Language like C++ or JAVA support no argument function overloads; typescript seems not to.

@Izhaki Izhaki changed the title Overloading with/without parameters Overloading with/without arguments throws a compiler error Nov 13, 2015
@mhegazy
Copy link
Contributor

mhegazy commented Nov 13, 2015

please see the handbook on how to express function overloads in TypeScript: https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/Functions.md#overloads

@mhegazy mhegazy closed this as completed Nov 13, 2015
@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Nov 13, 2015
@Izhaki
Copy link
Author

Izhaki commented Nov 14, 2015

@mhegazy, thanks for your reply.

I assume you are aware I was consulting these docs before filing the issue (how would I know about overloads otherwise?).

But the issue remains: you can overload functions so long you provide a strict type, but there seems to be no way of having a function that takes no parameters as part of the overloading mechanism.

If I'm wrong about this. Please let me know.
If I'm right, then I think this is an issue, since in languages like C++ or JAVA a no arguments overload is valid.

Thanks!

@DanielRosenwasser
Copy link
Member

how would I know about overloads otherwise?

Well you already said you were familiar with Java and C#. 😉

there seems to be no way of having a function that takes no parameters as part of the overloading mechanism.

The following should work.

    restoreState(): void;
    restoreState(aState: TransformerState): void
    restoreState(aState?: TransformerState) {
        if (aState) {
            this.state = astate;
        }
        else {
            this.restoreState(this.stateStack[stateStack.length - 1]);
        }
    }

But using more canonical TypeScript, you can get rid of the overloads altogether and just give your parameter a default value.

    restoreState(aState = this.stateStack[stateStack.length - 1]) {
        this.state = aState
    }

@Izhaki
Copy link
Author

Izhaki commented Nov 15, 2015

Thanks @DanielRosenwasser.

It may sound odd, but I don't actually need this type overriding at the moment. I was giving this a go and noticed it doesn't work.

Your solution Daniel will work. But that's not the point...

My argument that seeing as overloading is supported by the compiler for functions with arguments, it should (that is, it surely will surface at some point as a requirement) also support no parameter functions.

In other words, the framework should support this; it's a missing feature.

@DanielRosenwasser
Copy link
Member

I don't understand you argument. I clearly gave you an example of a zero-parameter overload above, so what exactly do you mean?

@Izhaki
Copy link
Author

Izhaki commented Nov 15, 2015

Oh OK... I think I understand where the confusion is.

The docs say:

In order for the compiler to pick the correct typecheck, it follows a similar process to the underlying JavaScript. It looks at the overload list, and proceeding with the first overload attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload. For this reason, its customary to order overloads from most specific to least specific.

This completely gives the impression that the compiler is the one calling the correct overload based on the parameters provided.

So I just assumed the compiler will call the right function based on its parameters:

draw( aRect : Rect ) {
}

draw( aPoint: Point ) {
}

But this throws error TS2393: Duplicate function implementation.

So it's either the compiler doesn't resolve overloads for you, or it depends on a return type?

Sorry, but I'm probably biased by other languages where the code above is a valid one.

@mhegazy
Copy link
Contributor

mhegazy commented Nov 16, 2015

JavaScript, and so is TypeScript, does not have a concept of function overloads like in other languages. so you definition of two draw functions is a redefinition of the same function, and in pure JS last one wins (i.e. the first one will never be called) and in TS it is an error.

JS developers use checking for parameter types, values or count to achieve a form of overloading. this is similar to what @DanielRosenwasser mentioned, and similar to the samples in the documentation. There is nothing different in this respect in TypeScript.

The only thing that TypeScript adds here is the ability to describe these overloads by adding an overload set to a function implementation. again using @DanielRosenwasser's example:

    restoreState(): void;
    restoreState(aState: TransformerState): void
    restoreState(aState?: TransformerState) {
    ....
   }

It is OK to call this method with 0 or 1 arguments. it is error otherwise. it is still the implementation responsibility to do the actual "overloading":

    restoreState(aState?: TransformerState) {
        if (aState) {   // 1 argument passed
            this.state = astate;
        }
        else {   // 0 arguments passed
            this.restoreState(this.stateStack[stateStack.length - 1]);
        }
    }

hope that helps.

@Izhaki
Copy link
Author

Izhaki commented Nov 16, 2015

Thanks @mhegazy,

This is clearer now. Two points:

  • I think the documentation is really confusing because it truly infers that the compiler supports overloading just like in other languages.
  • I may be wrong, but I believe the compiler can actually support this? That is, it can maintain a list of overrides (functions with body) and emit the router function automatically? This will put the overloading capabilities of typescript on par with those of other OOP languages.

@kitsonk
Copy link
Contributor

kitsonk commented Nov 16, 2015

The clearness documentation maybe debatable, because while it describes it, it provides examples of how to utilise it, which your examples I am afraid to follow the documentation.

I may be wrong, but I believe the compiler can actually support this? That is, it can maintain a list of overrides (functions with body) and emit the router function automatically? This will put the overloading capabilities of typescript on par with those of other OOP languages.

This has been discussed before in other threads here, the only way to realistically achieve this is by emitting some sort of run-time overhead, which is very much against the design goals of TypeScript. In particular:

  1. Impose no runtime overhead on emitted programs.

As well as the non-goal of:

Exactly mimic the design of existing languages. Instead, use the behavior of JavaScript and the intentions of program authors as a guide for what makes the most sense in the language.

@Izhaki
Copy link
Author

Izhaki commented Nov 16, 2015

Thanks @kitsonk. That makes sense.

One thought though:

Impose no runtime overhead on emitted programs.

That's very reasonable, but note that if one is after function overloads one has to follow the documentation example (the router function), which are exactly the overhead the framework is trying not to introduce.

So in a way, anyone who wishes to use the overloads feature will introduce the same overhead that the framework would otherwise introduce.

So the whole thing is possibly half-baked? I suspect you say:

We give you this feature, but since we don't want to introduce overhead, you'll have to introduce it yourself in order to use the feature.

Obviously client code will be more prone to errors than framework code.

If it would be up to me, I would either not provide it at all, or provide the full mechanism asserting it introduces a runtime overhead. But wouldn't leave it in a state where in order to be used a manual introduction of overload is necessary.

Anyhow, as you said, this has been discussed before, and to be frank is not a make-or-break feature.

So thanks everyone for their comments.

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants