Skip to content

Generic parameter defaults in arrow functions confused as jsx elements in tsx files #45939

Closed

Description

const OkInTsx = function <A = string>() {
  return 'ok in ts file';
};

export const BrokeInTsx = <A = string>() => {
  return 'ok in ts file';
};

To replicate, copy that code in a ts file (v3.3+ tested, updated vscode). It should be ok. Rename ts to tsx and the generic parameter default will be considered a jsx element and therefore a syntax error. I discovered this doing some codegen into a tsx file. If we are writing our own code, we can work around, but it seems jsx and generic parameter defaults on arrow functions aren't working together at the moment.

Activity

  1. MartinJohns commented on Sep 17, 2021

    @MartinJohns
    Contributor

    You forgot to fill out the issue template. It asks for search terms you used to find existing issues. Duplicate of #15713.

  2. matt-erhart commented on Sep 18, 2021

    @matt-erhart
    Author

    Whoops, don't know why I didn't get a template that time. This is a slightly different issue which I show in the ts playground here. Basically, there are workarounds for generics on arrow functions, but not for generic parameter defaults with the = in there. I can repost with template if it's actually new. I searched for typescript generic aliases, typescript generic renaming, typescript generics, advanced typescript generics, generic parameter defaults.

    // Known similar issue with generics https://github.com/microsoft/TypeScript/issues/15713
    
    //Work arrounds
    export const CommaWorkArroundForGenerics = <A,>() => {
      return 'ok in ts file';
    };
    
    export const ExtendsWorkArroundForGenerics = <A extends unknown>() => {
      return 'ok in ts file';
    };
    
    export const DontUseArrowFunctionsWorkArround = function <T = string>(x:T) {
      return x
    };
    
    // I believe a new issue without work arrounds for generic parameter defaults in arrow functions
    export const Broke1 = <IX = string,>(x:Ix) => { // no comma workarround
      return 'ok in ts file';
    };
    
    export const Broke2 = <IX = string extends unknown>(x:Ix) => { // no extends workarround
      return 'ok in ts file';
    };
  3. andrewbranch commented on Sep 23, 2021

    @andrewbranch
    Member

    Your last example gets the syntax wrong in general—the constraint needs to come before the default. It works if you fix that, except that the second-to-last example breaks parsing for everything after it. So the one thing that doesn’t work is an arrow function with a default but no constraint (as in Broke1), but for all intents and purposes you can always add extends unknown, so there’s still at least one workaround for everything you could need to do.

  4. matt-erhart commented on Sep 24, 2021

    @matt-erhart
    Author

    Aha, got it, thanks.

    export const WorkArroundExtendsCorrectSyntax = <Ix extends unknown = String >(x:Ix) => { 
      return 'ok in ts and tsx file';
    };
    
  5. locked as resolved and limited conversation to collaborators on Oct 21, 2025
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

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions