Skip to content

Method overloading does not work on TSX templates #9703

Description

@drewwyatt

TypeScript Version: 1.8.10
Code

import * as React from 'react';
import { Link } from 'react-router';

export interface ClickableProps {
    children?: string;
    className?: string;
}

export interface ButtonProps extends ClickableProps {
    onClick(event?: Event): void;
}

export interface LinkProps extends ClickableProps {
    to: string;
}

export function MainButton(buttonProps: ButtonProps): JSX.Element;
export function MainButton(linkProps: LinkProps): JSX.Element;
export function MainButton(props: ButtonProps | LinkProps): JSX.Element {
    const linkProps = props as LinkProps;
    if(linkProps.to) {
        return this._buildMainLink(props);
    }

    return this._buildMainButton(props);
}

function _buildMainButton({ onClick, children, className }: ButtonProps): JSX.Element {
    return(<button className={className} onClick={onClick}>{ children || 'MAIN BUTTON'}</button>);  
}

function buildMainLink({ to, children, className }: LinkProps): JSX.Element {
    return (<Link to={to}><button className={className}>{ children || 'MAIN BUTTON'}</button></Link>    );
}

/**
 * This works
 */

MainButton({ to: 'floop' }); // no errors
MainButton({ onClick: () => {} }); // no errors
MainButton(); // throws expected errors

/**
 * This does NOT work
 */

function buildSomeElement(): JSX.Element {
    return (
        <MainButton to='/some/path'>GO</MainButton>
    );
}

Expected behavior:

I would expect the buildSomeElement() function to not throw an error because the "to" attribute satisfies the second signature of the overloaded MainButton function (like what happens when this is called as a function and not used as a TSX element).

Actual behavior:

The buildSomeElement() function throws an error expecting an onClick attribute.

Activity

  1. RyanCavanaugh commented on Jul 13, 2016

    @RyanCavanaugh
    Member

    Does this work if the function is declared like so (without the explicit signatures)?

    export function MainButton(props: ButtonProps | LinkProps): JSX.Element {
        const linkProps = props as LinkProps;
        if(linkProps.to) {
            return this._buildMainLink(props);
        }
    
        return this._buildMainButton(props);
    }
  2. drewwyatt commented on Jul 16, 2016

    @drewwyatt
    Author

    Ryan Cavanaugh (@RyanCavanaugh) it does not. :( - that throws:

    Property 'to' does not exist on type 'IntrinsicAttributes & (ButtonType | LinkType)'
    
  3. mynameisstephen commented on Aug 17, 2016

    @mynameisstephen

    It looks like only the first overloaded method is being evaluated. Moving

    export function MainButton(linkProps: LinkProps): JSX.Element;

    above

    export function MainButton(buttonProps: ButtonProps): JSX.Element;

    works as expected.

  4. RyanCavanaugh commented on Aug 22, 2016

    @RyanCavanaugh
    Member

    This is actually rather complex but we're going to look at some targeted fix (mostly this example specifically and top-level union types in non-SFCs) in 2.1

  5. drewwyatt commented on Aug 23, 2016

    @drewwyatt
    Author

    Awesome!

  6. modified the milestones: TypeScript 2.1, on Oct 27, 2016
  7. 1 remaining item

  8. modified the milestones: , on Oct 31, 2016
  9. modified the milestones: TypeScript 2.2, on Dec 23, 2016
  10. faceyspacey commented on Jan 24, 2017

    @faceyspacey

    +1

  11. yuit commented on Feb 15, 2017

    @yuit
    Contributor

    James Gillmore (@faceyspacey) Drew Wyatt (@drewwyatt) the fix is now in master....we will now use similar overload resolution logic to figure out SFC. Give it a try and let us know!

  12. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CommittedThe team has roadmapped this issueFixedA PR has been merged for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions