Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
trusktr opened this issue Nov 30, 2018 · 9 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@trusktr
Copy link
Contributor

trusktr commented Nov 30, 2018

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

@trusktr trusktr 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'. Nov 30, 2018
@trusktr
Copy link
Contributor Author

trusktr commented Nov 30, 2018

(My tsconfig includes "declaration": true)

@weswigham
Copy link
Member

You

export const EventEmitter

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

@weswigham weswigham added the Question An issue which isn't directly actionable in code label Nov 30, 2018
@trusktr
Copy link
Contributor Author

trusktr commented Dec 1, 2018

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.

@trusktr
Copy link
Contributor Author

trusktr commented Dec 1, 2018

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

@trusktr trusktr closed this as completed Dec 1, 2018
@trusktr
Copy link
Contributor Author

trusktr commented Dec 3, 2018

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.

@trusktr trusktr reopened this Dec 3, 2018
@trusktr
Copy link
Contributor Author

trusktr commented Dec 3, 2018

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.

@weswigham
Copy link
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.

@trusktr
Copy link
Contributor Author

trusktr commented Dec 14, 2018

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

@typescript-bot
Copy link
Collaborator

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

3 participants