8000 Allow using types defined inside function body in the function's signature Β· Issue #61245 Β· microsoft/TypeScript Β· GitHub
[go: up one dir, main page]

Skip to content
Allow using types defined inside function body in the function's signatureΒ #61245
Closed as not planned
@KurtGokhan

Description

@KurtGokhan

πŸ” Search Terms

"type alias in function signature", "type alias in function body", "type scope", "duplicate types", "hoist type alias"

βœ… Viability Checklist

⭐ Suggestion

This is a weird request, and I am certain it's not going to be accepted easily. I am basically asking to break lexical scoping for this use case. But I want to show the pain point, so that maybe a better solution can be found.

My suggestion is to hoist type declarations at the top of a function body to outside of the function, so that those type declarations can be used in the function signature.

πŸ“ƒ Motivating Example

Suppose a function like this:

function myFunction<T1, T2>(param1: CalculateParam1Type<T1,T2>, param2: CalculateParam2Type<T1, T2>): CalculateReturnType<T1, T2> {
  type TParam1 = CalculateParam1Type<T1, T2>;
  type TParam2 = CalculateParam2Type<T1, T2>;
  type TReturn = CalculateReturnType<T1, T2>;

  const result: TReturn = { /* ... */ };

  return result;
}

Notice how I wrote the same types multiple times. It's often worse than that when you have more generic type parameters, and type parameters are named descriptively like TMyValue instead the short T1 etc. The code becomes unreadable quickly. To reduce code duplication, you often have to write intermediate generic types that are only used for that function, and still pass the long list of generics to that type each time.

Typescript should allow us to write the function above like:

function myFunction<T1, T2>(param1: TParam1, param2: TParam2): TReturn {
  type TParam1 = CalculateParam1Type<T1, T2>;
  type TParam2 = CalculateParam2Type<T1, T2>;
  type TReturn = CalculateReturnType<T1, T2>;

  const result: TReturn = { /* ... */ };

  return result;
}

This can be a breaking change, as TParam1 could exist outside of this function for example. In such a case, the type declaration that is outside should be picked to not cause a breaking change.

πŸ’» Use Cases

  1. What do you want to use this for?

Generic functions with complex types would benefit from this change. Library level types often need to handle many cases at once and make invalid states irrepresentable. That often requires complex types, and it goes out of hand without a feature like this.

  1. What shortcomings exist with current approaches?

Current approach is to duplicate the type everywhere it's needed. Duplicate code can lead to bugs. Also code becomes unreadable with large types.

  1. What workarounds are you using in the meantime?

Defining each type declaration multiple times.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DeclinedThe issue was declined as something which matches the TypeScript visionSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0