Skip to content

Improve Function Signature Syntax #29019

Closed

Description

@Enteleform

Suggestion

Please reconsider combining default parameters & type annotations in function signatures. This was already proposed in #7576, but the issue was closed shortly after Mohamed Hegazy (@mhegazy)'s post which made the following argument:

ultimately, every new syntax added is added complexity, for the user to learn and recognize, and for the compiler code base to maintain, so usually we try to limit complexity unless the value warrants it. and for destructuring, the syntax is already complex to start with, and we did not want to add yet another layer on top.

However, in reality the current syntax is more difficult to write & maintain than the proposed syntax. I'd argue that the proposed syntax would even be worth admitting into Breaking Changes in the long run, given that the change is timed & documented appropriately (even if that means waiting for a major version release).

Examples

//####################//
//###  Assertions  ###//
//####################//

                  //  [arg_1, arg_2, arg_3]
  foo()           //  [0,     0,     0    ]
  foo({})         //  [0,     0,     0    ]
  foo({arg_1:1})  //  [1,     0,     0    ]
  
  
//#####################################//
//###  Proposed Function Signature  ###//
//#####################################//

  // easy to parse
  // easy to maintain
  
    function foo({arg_1:number=0, arg_2:number=0, arg_3:number=0}){
      // ...
    }
    
    function foo({
      arg_1: number = 0,
      arg_2: number = 0,
      arg_3: number = 0,
    }){
      // ...
    }


//####################################//
//###  Current Function Signature  ###//
//####################################//
  
  // difficult to parse
  // difficult to maintain (redundant code)
    
    function foo({arg_1=0, arg_2=0, arg_3=0}:{arg_1?:number, arg_2?:number, arg_3?:number}={}){
      // ...
    }
      
    function foo(
      {arg_1=0, arg_2=0, arg_3=0}
      :{arg_1?:number, arg_2?:number, arg_3?:number}
      ={}
    ){
      // ...
    }
  
  
  // ok to parse
  // difficult to maintain (redundant code, formatting is time consuming)
  
    function foo(
      {arg_1=0,       arg_2=0,       arg_3=0      }:
      {arg_1?:number, arg_2?:number, arg_3?:number}={}
    ){
      // ...
    }


  // ok to parse
  // difficult to maintain (redundant code)
  // 
  // This is currently the most balanced option for [writability, readability, maintainability],
  // but results in double the lines of code; which quickly adds up to 100s or 1000s
  // of lines of unnecessary code in a larger project. This boilerplate creates extra work
  // & detracts from TypeScript's developer experience by forcing developers to spend extra time
  // crafting & tweaking function signatures instead of writing more pertinent code.
  
    function foo({
      arg_1 = 0,
      arg_2 = 0,
      arg_3 = 0,
    }:{
      arg_1?: number,
      arg_2?: number,
      arg_3?: number,
    }={}){
      // ...
    }

Note

A few people have mentioned that there may be a conflict with the {a:b=c} syntax. However, the exact syntax is not the purpose of this recommendation, and I invite any suggestions for a more preferable syntax that does not have any compatibility issues. The important part of this suggestion is that the syntax should be able to handle type annotations & default parameters in one section instead of two.

Search Terms

destructuring destructure function signature default parameters type annotations

Activity

  1. dmytro-lymarenko commented on Dec 14, 2018

    @dmytro-lymarenko

    Why not this:

    interface FooArgs {
    	arg_1?: number;
    	arg_2?: number;
    	arg_3?: number;
    }
    
    function foo(arg: FooArgs) {
    	const { arg_1 = 0, arg_2 = 0, arg_3 = 0 } = arg;
    }

    ?

  2. dmytro-lymarenko commented on Dec 14, 2018

    @dmytro-lymarenko

    Plus, this syntax

    { arg_1: number = 0 }

    means that you rename arg_1 to number and set its initial value to 0

  3. Enteleform commented on Dec 14, 2018

    @Enteleform
    Author

    dmytro-lymarenko

    interface FooArgs {
    	arg_1?: number;
    	arg_2?: number;
    	arg_3?: number;
    }
    
    function foo(arg: FooArgs) {
    	const { arg_1 = 0, arg_2 = 0, arg_3 = 0 } = arg;
    }

    has the same issue as mentioned in the OP.

     
    It would be much more concise as

    function foo({arg_1:number=0, arg_2:number=0, arg_3:number=0}){
    }

    which eliminates code duplication.
     


     
    Regarding the potential syntax conflict you brought up:
    {arg_1: number = 0}

    I'm not sure that the assignment syntax directly conflicts with the function signature syntax. Even if it does, the syntax I proposed is definitely open to adjustment. The main point is to reduce excess/duplicate code.

    This could just as easily be accomplished with

    foo({{arg_1: number = 0}})
    foo({<number> arg_1 = 0})

    or some other similar, non-conflicting syntax.

  4. j-oliveras commented on Dec 14, 2018

    @j-oliveras
    Contributor

    As dmytro-lymarenko said: the proposed syntax collides with javascript rename on destructuring arguments (using this example: function foo({arg_1:number=0}) {} is put into a variable named number the value of the property named args_1 from the first parameter, if that property not exists use 0.

    This proposed

    function foo({arg_1:number=0, arg_2:number=0, arg_3:number=0}){
    }

    has the problem that all there values must be stored to the same variable as you can see into playground.

  5. Enteleform commented on Dec 14, 2018

    @Enteleform
    Author

    Jordi Oliveras Rovira (@j-oliveras)

    I addressed that issue in the second half of my response to dmytro-lymarenko. The *exact* syntax that I proposed is not important, it can definitely be altered as needed to make it work.

  6. weswigham commented on Dec 14, 2018

    @weswigham
    Member

    Still a dupe of #7576 and it's still declined for all the same reasons.

  7. Enteleform commented on Dec 14, 2018

    @Enteleform
    Author

    Wesley Wigham (@weswigham)

    I'd argue that it should be reconsidered/reopened, especially when considering the related issue in #5326. If these issues are not handled properly, then TypeScript's signatures will become even more redundant and troublesome to maintain than they already are. Also, this is clearly something that users want, as noted by the continued activity in #7576 after it was closed. Multiple users have even commented that they avoid using destructuring and/or TypeScript altogether because of these issues. The initial specification was designed poorly, and it should be rectified rather than implementing clumsy workarounds every time a new feature needs to be added.

    Breaking changes have been made for certain features, and I think that solving the cluttered function signature issues that currently exist would be worthy of a breaking change. Having a single-section function signature would then allow all future changes to be implemented much more easily.

  8. typescript-bot commented on Dec 17, 2018

    @typescript-bot
    Contributor

    This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

  9. 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