Skip to content
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

allow class-scoped type declarations #55996

Closed
5 tasks done
martaver opened this issue Oct 5, 2023 · 2 comments
Closed
5 tasks done

allow class-scoped type declarations #55996

martaver opened this issue Oct 5, 2023 · 2 comments

Comments

@martaver
Copy link

martaver commented Oct 5, 2023

πŸ” Search Terms

"class member types", "class scoped type members", "class level type declarations"

βœ… Viability Checklist

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

⭐ Suggestion

Allow the declaration of types within a class's instance scope that can use it's generic arguments, and be available to all members.

πŸ“ƒ Motivating Example

Sometimes we get many repetitive types in a class' definition.

Take for example:

interface IFoo<A, B> { foo(args: { value: A }): B }

class Foo<A, B> implements IFoo<A, b> {

  foo(...args: Parameters<IFoo<A, B>['foo']>): ReturnType<IFoo<A, B>['foo']> {
    throw new Error('Method not implemented.');
  }
}

Here we want to refer to the types of the generic IFoo that the class implements, but to access them we need to write the full IFoo<A,B> every time.

It would be handy to be able to create a class-scoped type alias, to be able to DRY this up:

interface IFoo<A, B> { foo(args: { value: A }): B }

class Foo<A, B> implements IFoo<A, b> {

  type F = IFoo<A,B>
  type Args = Parameters<F['foo']>
  type Ret = ReturnType<F['foo']>

  foo(...args: Args): Rer { // <-- clears up the signature, separates type definitions from implementation
    throw new Error('Method not implemented.');
  }
}

However, Typescript doesn't allow types to be declared in a class' scope.

For reference, the equivalent is possible in a closure:

interface IFoo<A, B> { foo(args: { value: A }): B }

function Foo<A, B>(): IFoo<A, B> {

  type F = IFoo<A, B>

  return {
    foo(...args: Parameters<F['foo']>): ReturnType<F['foo']> {
      throw new Error('Method not implemented.');
    }
  }
}

This would be a significant quality of life improvement, allowing developers to better express their intent.

πŸ’» Use Cases

  1. What do you want to use this for?
  • enhancing readaibility & expressiveness
  • publicly exposing utility types on class instances, e.g. type myType = Foo.F (potentially)
  1. What shortcomings exist with current approaches?
  • Developers who want to use classes are forced to write a lot of unnecessary types.
  1. What workarounds are you using in the meantime?
  • It's possible to use default generic arguments as a kind of type alias, but this is generally verbose and muddies intent.
  • Mostly, I just eat the extra keystrokes.
@MartinJohns
Copy link
Contributor

Duplicate of #7061.

@martaver
Copy link
Author

martaver commented Oct 5, 2023

Thanks :) Closing in favour of: #7061.

@martaver martaver closed this as completed Oct 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants