Skip to content

[bug?] Cannot find name 'EventEmitter', property 'channel' of exported interface has or is using private name 'EventEmitter'. #28754

Description

@trusktr

TypeScript Version: 3.3.0-dev.20181129

Search Terms:

The search results led to issues like this one: #6307

Code

// ./Events.ts
class EventTypes {
  constructor(
    public SOME_EVENT: any,
    public OTHER_EVENT: any,
  ) {}
}

export const Events = {} as { [k in keyof EventTypes]: k }

for (const key in new (EventTypes as any)) {
    Events[key] = key
}

import * as events from 'events' // definitions are from `@types/node`

// our own (better, more type-safe) definition of EventEmitter
interface BetterEventEmitter<EventTypes> {
  new(): BetterEventEmitter<EventTypes>
  addListener<EventName extends keyof EventTypes> (event: EventName, listener: (arg: EventTypes[EventName]) => void);
  on<EventName extends keyof EventTypes> (event: EventName, listener: (arg: EventTypes[EventName]) => void);
  once<EventName extends keyof EventTypes> (event: EventName, listener: (arg: EventTypes[EventName]) => void);
  removeListener<EventName extends keyof EventTypes> (event: EventName, listener: (arg: EventTypes[EventName]) => void);
  removeAllListeners<EventName extends keyof EventTypes>(event?: EventName): this;
  emit<EventName extends keyof EventTypes>(event: EventName, arg: EventTypes[EventName]): boolean;
  eventNames<EventName extends keyof EventTypes>(): Array<EventName>;
  setMaxListeners(n: number): this;
  getMaxListeners(): number;
  listeners<EventName extends keyof EventTypes>(event: EventName): (arg: EventTypes[EventName]) => void[];
  listenerCount<EventName extends keyof EventTypes>(type: EventName): number;
  prependListener<EventName extends keyof EventTypes>(event: EventName, listener: (arg: EventTypes[EventName]) => void): this;
  prependOnceListener<EventName extends keyof EventTypes>(event: EventName, listener: (arg: EventTypes[EventName]) => void): this;
}

// override Node EventEmitter with our definition
export const EventEmitter = events.EventEmitter as unknown as BetterEventEmitter<EventTypes>
// consumer.ts
import { Events, EventEmitter } from './models/Events' // ERROR: `EventEmitter` is declared but its value is never read.

const channel = new EventEmitter // works fine, no error!

class Foo {
  channel: EventEmitter // ERROR, Cannot find name 'EventEmitter'
}

export interface Bar {
  channel: EventEmitter // ERROR, Cannot find name 'EventEmitter', property 'channel' of exported interface has or is using private name 'EventEmitter'.
}

Expected behavior:

I expect not to get the ERRORs I've marked in the above comments.

Actual behavior:

I'm getting those errors.

Playground Link:

I can't put multiple files in Playground or install dependencies.

Related Issues:

#6307

Activity

  1. changed the title [-]Cannot find name 'EventEmitter', property 'channel' of exported interface has or is using private name 'EventEmitter'.[/-] [+][bug?] Cannot find name 'EventEmitter', property 'channel' of exported interface has or is using private name 'EventEmitter'.[/+] on Nov 30, 2018
  2. trusktr commented on Nov 30, 2018

    @trusktr
    ContributorAuthor

    (My tsconfig includes "declaration": true)

  3. weswigham commented on Nov 30, 2018

    @weswigham
    Member

    You

    export const EventEmitter

    but you also need to export a type named EventEmitter if you want to reference one as such.

  4. trusktr commented on Dec 1, 2018

    @trusktr
    ContributorAuthor

    Ah I see, yep it works. It's not so intuitive though. Isn't it obvious that I'm exporting a constructor (therefore a type)? Seems like the compiler should be able to pick that up.

  5. trusktr commented on Dec 1, 2018

    @trusktr
    ContributorAuthor

    I'll close this though, as that's indeed how to make it work, but curious what you think about the compiler being able to detect that I'm exporting a constructor (and therefore a type).

  6. trusktr commented on Dec 3, 2018

    @trusktr
    ContributorAuthor

    This declaration stuff is funky. I'm on typescript 3.3.0-dev.20181129.

    Now that I fixed that problem by adding the export of the type, not just the runtime value, I now have an error in another file:

    Parameter 'channel' of constructor from exported class has or is using name 'BetterEventEmitter' from external module "/path/to/Events.ts" but cannot be named.

    on some code that looks like

    import { Events, EventEmitter } from '../models/Events'
    
    export abstract class Foo {
      protected constructor(
        readonly channel?: EventEmitter, // ERROR here
      ) {
        // ...
      }
      // ...
    }

    Here's a screenshot:

    screen shot 2018-12-03 at 10 37 24 am

    Looks like maybe #9944 is not fixed.

    However, this only happens to me in one file, but I can't reproduce it in another file. So something is weird here.

  7. trusktr commented on Dec 3, 2018

    @trusktr
    ContributorAuthor

    I was able to fix the previous comment's error by changing

    interface BetterEventEmitter<EventTypes> {

    to

    export interface BetterEventEmitter<EventTypes> {

    but I shouldn't have to do that, I'm not importing that name anywhere, it is only ever used in the definition of what EventEmitter is.

    Looks like that "declaration": true, feature is not working as expected.

  8. weswigham commented on Dec 3, 2018

    @weswigham
    Member

    Use export { BetterEventEmitter as EventEmitter } instead of export type EventEmitter = BetterEventEmitter - the first establishes a usable alias, while due to some design limitations, the second isn't something we usually can locate for declaration emit.

  9. trusktr commented on Dec 14, 2018

    @trusktr
    ContributorAuthor

    It's hard to understand why, as with my eyes I can locate it just fine. Thanks for that tip!

  10. typescript-bot commented on Jul 13, 2019

    @typescript-bot
    Contributor

    This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow.

  11. 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