Typescript: Expose Self as a type within classes

Created on 8 May 2020  ·  2Comments  ·  Source: microsoft/TypeScript

often when Declaring a class it's very useful to reference the Class itsself as a type internally

For Example

class SomeReallyLongClassNameComponentThing {
  valueA: SomeReallyLongInportedValueA;
  valueB: SomeReallyLongInportedValueb;

  doSomethingWithA(val: SomeReallyLongClassNameComponentThing['valueA']) {}
  doSomethingWithB(val: SomeReallyLongClassNameComponentThing['valueB']) {}
}

It's nice that I can reference the className inside the class Decloration..
During refactoring I can change the type of valueA with a single edit.

however:

  • The name of the class can be long
  • Name of the class is changeable

So we have resorted to making single classes perfile and using this syntax

type Self = SomeReallyLongClassNameComponentThing;
class SomeReallyLongClassNameComponentThing {
  valueA: SomeReallyLongInportedValueA;
  valueB: SomeReallyLongInportedValueb;

  doSomethingWithA(val: Self['valueA']) {}
  doSomethingWithB(val: Self['valueB']) {}
}

Search Terms

Self type in classes, Class Scope Types

Suggestion

It would be awesome if type Self was automatically declared as a type inside the class Declaration..
(or if you could declare Self only in the scope of the class Declaration

ie 1. scoping

export class SomeReallyLongClassNameComponentThingOne {
  type Self = SomeReallyLongClassNameComponentThingOne;
  valueA: SomeReallyLongInportedValueA;
  valueB: SomeReallyLongInportedValueb;

  doSomethingWithA(val: Self['valueA']) {} 
  doSomethingWithB(val: Self['valueB']) {}
}

export class SomeReallyLongClassNameComponentThingTwo {
  type Self = SomeReallyLongClassNameComponentThingTwo;
  valueOne: SomeReallyLongInportedValueOne;
  valueTwo: SomeReallyLongInportedValueTwo;

  doSomethingWithA(val: Self['valueOne']) {}
  doSomethingWithB(val: Self['valueTwo']) {}
}

-ie 2. AutoDeclared

export class SomeReallyLongClassNameComponentThingOne {
  valueA: SomeReallyLongInportedValueA;
  valueB: SomeReallyLongInportedValueb;

  doSomethingWithA(val: Self['valueA']) {} 
  doSomethingWithB(val: Self['valueB']) {}
}

export class SomeReallyLongClassNameComponentThingTwo {
  valueOne: SomeReallyLongInportedValueOne;
  valueTwo: SomeReallyLongInportedValueTwo;

  doSomethingWithA(val: Self['valueOne']) {}
  doSomethingWithB(val: Self['valueTwo']) {}
}

Use Cases

  • Easy Self reference and access to class Types
  • Easier refactoring of Names
  • Scoping of type Variables

Examples

Checklist

My suggestion meets these guidelines:

  • [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [x] This wouldn't change the runtime behavior of existing JavaScript code
  • [x] This could be implemented without emitting different JS based on the types of the expressions
  • [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [x] This feature would agree with the rest of TypeScript's Design Goals.
Duplicate

Most helpful comment

What about this['valueA'] and this['valueB']? It works and gives the behaviour you're describing:
https://www.typescriptlang.org/play/#code/MYGwhgzhAEDKD2BbApgJWWEICeAZeAdgOYDC4UAcmCiUgA6HIEAuAKgBYCWx0A3gFDRoAN0wBXZAEEA-AC5oEZgCduRANyCR45ACE50AmMQAjZEo2aAJvAQpmXYgHVO9yQApRIefc4QA2gDknhKSAQC6AJR8AL5WNkjIPk4u7DoemN5c-kHaOuFRvLGx-MCEitDcimAEwMjQALwGyADucAnomDj4xGSQEFQ09IwsHKpuERaVzNW1AHTWtokORM6ubgHN8EoA1hABE-xAA

All 2 comments

What about this['valueA'] and this['valueB']? It works and gives the behaviour you're describing:
https://www.typescriptlang.org/play/#code/MYGwhgzhAEDKD2BbApgJWWEICeAZeAdgOYDC4UAcmCiUgA6HIEAuAKgBYCWx0A3gFDRoAN0wBXZAEEA-AC5oEZgCduRANyCR45ACE50AmMQAjZEo2aAJvAQpmXYgHVO9yQApRIefc4QA2gDknhKSAQC6AJR8AL5WNkjIPk4u7DoemN5c-kHaOuFRvLGx-MCEitDcimAEwMjQALwGyADucAnomDj4xGSQEFQ09IwsHKpuERaVzNW1AHTWtokORM6ubgHN8EoA1hABE-xAA

We couldn't make Self have a new meaning (it could already mean something else), so the only plausible solution would be to permit local type aliases in class bodies, which is #7061

Was this page helpful?
0 / 5 - 0 ratings