Skip to content

Suggestion: syntax for overloading function expressions #16731

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

Closed
OliverJAsh opened this issue Jun 24, 2017 · 4 comments
Closed

Suggestion: syntax for overloading function expressions #16731

OliverJAsh opened this issue Jun 24, 2017 · 4 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@OliverJAsh
Copy link
Contributor

Currently it is only possible to define function overloads for function declarations.

Sometimes it is desirable to use function expressions instead of function declarations. It would be nice if the function overload feature was applicable to function expressions as well.

By function expression, I mean something like this:

const identity = <X>(x: X) => x;
@ikatyang
Copy link
Contributor

You can use call signature to do such things:

const identity: {
  <X extends string>(x: X): X;
  <X extends number>(x: X): X;
} = <X>(x: X) => x;
function identity<X extends string>(x: X): X;
function identity<X extends number>(x: X): X;
function identity<X>(x: X): X {
  return x;
}

@OliverJAsh
Copy link
Contributor Author

Of course, thank you!

@OliverJAsh
Copy link
Contributor Author

OliverJAsh commented Jun 25, 2017

I notice that when I only specify the call signature on the interface with no inline function parameter/return types, I get an error:

{
    type identity = {
        (x: string): string;
        (x: number): number;
    }
    
    // error: Parameter 'x' implicitly has an 'any' type
    const identity: identity = (x) => x;
}

I would expect the x param to be inferred as string | number. Is this a bug I should open a separate issue for?

@ikatyang
Copy link
Contributor

x should never be inferred as string | number, since it will cause (A | B) -> (A | B) instead of (A -> A) | (B -> B), so I think it is correct to be inferred as any.

const identity: identity = (x: string | number) => x;
//    ^^^^^^^^ [ts]
// Type '(x: string | number) => string | number' is not assignable to type 'identity'.
//   Type 'string | number' is not assignable to type 'string'.
//     Type 'number' is not assignable to type 'string'.

I think using generic is the correct way but it seems something wrong with it.

type identity = {
  (x: string): string;
  (x: number): number;
}
    
// no error as expected
const identity: identity = <T>(x: T) => x;
type test = {
  (x: string): string;
  (x: number): number;
  (x: boolean): object;
}
    
// expected error but passed
const test: test = <T>(x: T) => x;

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Jun 26, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 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

3 participants