Search code examples
javascripttypescriptoopoverridingtsc

why i can't define interface or type inside typescript class


I want to define interface | type inside the typescript class here is the code:

class MyClass {
    interface IClass {
        name: string,
        id: string
    }
}

but I'm getting this error: Unexpected token. A constructor, method, accessor, or property was expected.

Exactly what I want to achieve:

I'm making a framework where the user to extends the base class Randoms and override a few methods of the base but I'm not getting any type of intelligence in the child class.
here is the code:

abstract class RandomsRoute {
   public get (req:Resquest, res:Response): Promise <void> { res.send ('') }
}

// client side

import RandomsRoute, { Request, Response } from '@my-pkg'

class Client extends RandomsRoute {
   // public get (req, res) {res.send('client side')} // error here
   public get (req: Request, res: Response): Promise <void> { res.send ('') }
}

here is the part:

{ Request, Response } from '@my-pkg'

I don't want the user to make lots of imports can we simplify this anymore or maybe provide some better APIs to user?


Solution

  • It is not currently possible to declare types or interfaces directly in the scope of a class body. There is a feature request for it at microsoft/TypeScript#7061, but it's not part of the language. Even if it were, it's not clear that you'd be able to export the types out of the class. For example, you can define types in functions, but the definitions of these types are invisible outside the function:

    function foo() {
      interface Foo {
        a: string,
        b: number;
      }
    }
    
    const f: Foo = {a: "", b: 1}; // error!
    // ----> ~~~ cannot find name Foo
    
    const g: foo.Foo = {a: "", b: 1}; // error!
    // ----> ~~~ cannot find namespace foo
    
    function foo() {
      export interface Foo { // error!
      //~~~~ <-- modifiers cannot appear here.
        a: string,
        b: number;
      }
    }
    

    So you probably don't really want to define your interface inside the class.


    Instead, what you can do, as mentioned in this comment on microsoft/TypeScript#7061 is merge the class with a namespace from which you export your type:

    export class MyClass {
    
    }
    export declare namespace MyClass {
      export interface IClass {
        name: string,
        id: string
      }
    }
    

    Then, in your other file, you can import MyClass and get both the class and the namespace:

    import { MyClass } from '@my-pkg'
    const c: MyClass = new MyClass();
    const i: MyClass.IClass = { name: "", id: "" };
    

    Playground link to code