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

Move the strongly-typed Typed types into the main types #69

Merged
merged 12 commits into from
Dec 28, 2020
Merged
14 changes: 7 additions & 7 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ type DatalessEventNames<EventData> = {
[Key in keyof EventData]: EventData[Key] extends undefined ? Key : never;
}[keyof EventData];


/**
Emittery is a strictly typed, fully async EventEmitter implementation. Event listeners can be registered with `on` or `once`, and events can be emitted with `emit`.

Expand Down Expand Up @@ -326,11 +325,12 @@ declare class Emittery<
@returns A method to unsubscribe.
*/
onAny(
listener: <Name extends keyof EventData>(
eventName: Name,
eventData?: EventData[Name]
listener: (
eventName: keyof EventData,
eventData: EventData[keyof EventData]
) => void
): Emittery.UnsubscribeFn;

/**
Get an async iterator which buffers a tuple of an event name and data each time an event is emitted.

Expand Down Expand Up @@ -373,9 +373,9 @@ declare class Emittery<
Remove an `onAny` subscription.
*/
offAny(
listener: <Name extends keyof EventData>(
eventName: Name,
eventData?: EventData[Name]
listener: (
eventName: keyof EventData,
eventData: EventData[keyof EventData]
) => void
): void;

Expand Down
130 changes: 107 additions & 23 deletions index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,139 @@
import {expectType, expectError} from 'tsd';
import Emittery = require('.');
import { expectType, expectError } from "tsd";
import Emittery = require(".");

// emit
{
const ee = new Emittery();
ee.emit('anEvent');
ee.emit('anEvent', 'some data');
ee.emit("anEvent");
sindresorhus marked this conversation as resolved.
Show resolved Hide resolved
ee.emit("anEvent", "some data");
}

// on
{
const ee = new Emittery();
ee.on('anEvent', () => undefined);
ee.on('anEvent', () => Promise.resolve());
ee.on('anEvent', data => undefined);
ee.on('anEvent', data => Promise.resolve());
ee.on(Emittery.listenerAdded, ({eventName, listener}) => {});
ee.on(Emittery.listenerRemoved, ({eventName, listener}) => {});
const off = ee.on('anEvent', () => undefined);
ee.on("anEvent", () => undefined);
ee.on("anEvent", () => Promise.resolve());
ee.on("anEvent", data => undefined);
ee.on("anEvent", data => Promise.resolve());
ee.on(Emittery.listenerAdded, ({ eventName, listener }) => {});
ee.on(Emittery.listenerRemoved, ({ eventName, listener }) => {});
const off = ee.on("anEvent", () => undefined);
off();
}

// off
{
const ee = new Emittery();
ee.off('anEvent', () => undefined);
ee.off('anEvent', () => Promise.resolve());
ee.off('anEvent', data => undefined);
ee.off('anEvent', data => Promise.resolve());
ee.off("anEvent", () => undefined);
ee.off("anEvent", () => Promise.resolve());
ee.off("anEvent", data => undefined);
ee.off("anEvent", data => Promise.resolve());
}

{
const ee = new Emittery();
expectError(ee.emit('anEvent', 'some data', 'and more'));
expectError(ee.emit("anEvent", "some data", "and more"));
}

{
const ee = new Emittery();
expectError(ee.on('anEvent', (data: any, more: any) => undefined));
expectError(ee.on("anEvent", (data: any, more: any) => undefined));
}

// Strict typing
// Strict typing for emission
{
const ee = new Emittery<{
value: string;
open: undefined;
close: undefined;
}>();
ee.emit('open');
ee.emit('close');
ee.emit('value', 'test');
expectError(ee.emit('value'));
expectError(ee.emit('open', 'test'));
ee.emit("open");
ee.emit("close");
ee.emit("value", "test");
expectError(ee.emit("value"));
expectError(ee.emit("open", "test"));
}

// Strict typing for listeners
{
const ee = new Emittery<{
value: string;
open: undefined;
close: undefined;
}>();
ee.on("open", () => {});
ee.on("open", argument => {
expectType<undefined>(argument);
});

ee.on("value", () => {});
ee.on("value", argument => {
expectType<string>(argument);
});

const listener = (value: string) => undefined;
ee.on("value", listener);
ee.off("value", listener);
ee.once("value").then(listener);

expectError(ee.on("value", (value: number) => {}));
}

// Strict typing for onAny, offAny listeners
{
const ee = new Emittery<{
value: string;
open: undefined;
close: undefined;
other: number;
}>();

ee.onAny((name, data) => {
expectType<"value" | "open" | "close" | "other">(name);
expectType<string | number | undefined>(data);
});

const listener = (name: string) => {};
ee.onAny(listener);
ee.offAny(listener);
}

// Strict typing for onAny, offAny listeners for an Emittery that only has listeners with arguments
{
const ee = new Emittery<{
value: string;
other: number;
}>();

ee.onAny((name, data) => {
expectType<"value" | "other">(name);
expectType<string | number>(data);
});
}

// Strict typing for anyEvent iterator
{
const testAnyEvent = async () => {
const ee = new Emittery<{
value: string;
open: undefined;
close: undefined;
}>();

for await (const event of ee.anyEvent()) {
expectType<"value" | "open" | "close">(event[0]);

expectType<string | undefined>(event[1]);
}

const ee2 = new Emittery<{
value: string;
other: number;
}>();

for await (const event of ee2.anyEvent()) {
expectType<"value" | "other">(event[0]);
expectType<string | number>(event[1]);
}
};
}