Description
π 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
- 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)
- What shortcomings exist with current approaches?
- Developers who want to use classes are forced to write a lot of unnecessary types.
- 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.