Skip to content

[ts] 'private' modifier cannot appear on a type member. #25163

Closed

Description

I declared an interface with private property method as the following snippet:

export interface TestInterface {
  auth: () => Promise<any>
  private findGist: (page: number) => Promise<any>
}

Butt i got error with the context [ts] 'private' modifier cannot appear on a type member. in vscode.
What's wrong?

Activity

  1. j-oliveras commented on Jun 22, 2018

    @j-oliveras
    Contributor

    You can only use private inside a class.

  2. RikkiGibson commented on Jun 22, 2018

    @RikkiGibson
    Member

    private means it should only be visible to members declared on the same type--but since interface members don't have implementations, there's no way to reference the private property. So it's just not allowed.

  3. RyanCavanaugh commented on Jun 22, 2018

    @RyanCavanaugh
    Member

    It looks like this is a question rather than a bug report. This issue tracker is for tracking bugs and active work on TypeScript itself, rather than a general forum for programmers using TypeScript to get help or ask questions.

    You can ask questions on sites like Stack Overflow. We are not able to provide one-on-one support on the issue tracker. Next time, please read the issue template carefully - it has important information on what kinds of reports can be acted on here, as well as links to useful TypeScript resources. Thanks!

  4. MutableLoss commented on Oct 27, 2018

    @MutableLoss

    I think there is a bit of confusion that leads up to this error. If the members defined in the class are private, and these same members are used in the interface, TS will not compile and complain that these members are not set as private.

    interface IInterface {
      memberOne: string
      memberTwo: string
    }
    
    class TestClass implements IInterface {
      private memberOne!: string
      private memberTwo!: string
    }
    

    Using the above will yield the following error:

    Class 'TestClass' incorrectly implements interface 'IInterface'.
      Property 'memberOne' is private in type 'TestClass' but not in type 'IInterface'.
    

    So if setting access modifiers on interfaces is not possible why does TS give this sort of error which implies there are? I'm guessing the overall idea is to not add private members in an interface, and if that's the case, maybe TS could offer an error to imply something along those lines instead?

  5. andykais commented on Feb 1, 2019

    @andykais

    do we currently have any way to mark interface properties as protected or private? Currently this is the best I can do:

    interface TestInterface {
      prop1: number
      prop2?: string
    }
    
    class TestClass {
      protected prop1: TestInterface['prop1']
      protected prop2: TestInterface['prop2']
    }

    though this isnt a great solution because if TestInterface had extra properties, no error would be thrown if they were missing from TestClass

  6. takahser commented on Feb 14, 2019

    @takahser

    I agree with 3desprit
    Why is this happening?

    edit

    Apparently,

    Interfaces define "public" contracts and as such it doesn't make sense to have protected or private access modifier on interfaces, which are more of a, let's call it, implementation detail. As such you can't do what you want with an interface.

    see original post on SO

  7. trusktr commented on Jun 30, 2019

    @trusktr
    Contributor

    What about protected? Seems like this is obviously needed (as opposed to private).

    I'm using types for mixin classes (it is inevitable to have to step around the class system and use types to make them work fully). And I'd like to be able to specify protected in some interfaces which I'm using along Constructor types to create the types minimal types of expected classes being passed to the mixins.

  8. trusktr commented on Jun 30, 2019

    @trusktr
    Contributor

    For example, it is necessary to use interfaces/types (and not class) in order to make a mixin class understand what methods a base class might possibly have:

    type PossibleCustomElement<T extends HTMLElement> = T & {
        protected connectedCallback?(): void // contrived example
        disconnectedCallback?(): void
        adoptedCallback?(): void
        attributeChangedCallback?(name: string, oldVal: string | null, newVal: string | null): void
    }
    
    // This is a mixin only for Web Components! :)
    export function WithUpdateMixin<T extends Constructor<HTMLElement>>(Base: T) {
        class WithUpdate extends Base as unknown as Constructor<PossibleCustomElement<HTMLElement>> {
            protected connectedCallback() {
                if (super.connectedCallback) super.connectedCallback()
            }
        }
    }

    And so you see, I want to be able to define certain possibly-existing method/properties from the Base class (which is constrained by type T), and if any of those methods are protected, then now they will all be public because there's no way to specify it in the mixin.

    For sake of argument, let's imagine that connectedCallback is a protected method in some subclasses of HTMLElement; suppose this is a convention in HTML world (I know, it actually isn't, this is just an example). Then it'd be convenient if all I had to do was add the protected keyword for it to just work.

  9. trusktr commented on Jun 30, 2019

    @trusktr
    Contributor

    Here's what we can do to make a type with access modifiers, although it emits an unused runtime class (based on some actual code I have, much omitted):

    type Constructor<T = object, A extends any[] = any[]> = new (...a: A) => T
    function Constructor<T = object>(Ctor: Constructor<any>) {
        return (Ctor as unknown) as Constructor<T>
    }
    
    // using a `class` instead of `interface` or `type`!
    class PossiblyWebComponent {
        protected childConnectedCallback?(child: Element): void
        protected childDisconnectedCallback?(child: Element): void
        protected _isPossiblyDistributedToShadowRoot?: boolean
        protected _distributedParent?: TreeNode 
    }
    
    function AwesomeMixin<T extends Constructor>(Base: T) {
        const Parent = SomeOtherMixin(Constructor<PossiblyWebComponent>(Base))
    
        class Awesome extends Parent {
            protected childConnectedCallback(child: Element) {
                if (super.connectedCallback) super.connectedCallback(child)
            }
    
            // ...
        }
    
        return Awesome as Constructor<Awesome & InstanceType<T>>
    }

    It is possible to run the code through some Babel or Webpack plugin to snip unused code.

    EDIT: Or maybe just use declare to prevent the runtime output. I almost forgot about that.

  10. Leandro-Hespanhol commented on Apr 11, 2022

    @Leandro-Hespanhol

    I think the solution lies in 'getters', here is an example:

    interface IFighter {
       strength: number;
       dexterity: number;
    }
    
    class Character implements IFighter {
      protected _strength: number;
      protected _dexterity: number;
      ...
      get strength() { return this._strength }
      get dexterity() { return this._dexterity }
    }

    That way you can implement an interface and still keep class attributes protected.

  11. Autumnlight02 commented on Aug 20, 2022

    @Autumnlight02
  12. ThaJay commented on Mar 13, 2023

    @ThaJay

    Type script seems more and more time consuming and convoluted as I learn it on an ever deepening level

  13. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions