Align EventEmitter definitions with TypeScript (#49206)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/49206

Changelog: [Internal]

Reviewed By: huntie

Differential Revision: D68953500

fbshipit-source-id: 0e936e8423f8792db34d6b44b1620dde5bd13a47
This commit is contained in:
Jakub Piasecki
2025-02-11 05:42:24 -08:00
committed by Facebook GitHub Bot
parent 9612241597
commit 7dbfc1099c
5 changed files with 49 additions and 19 deletions
@@ -26,6 +26,9 @@ interface NativeModule {
export type {EventSubscription};
// $FlowFixMe[unclear-type] unclear type of events
type UnsafeObject = Object;
/**
* `NativeEventEmitter` is intended for use by Native Modules to emit events to
* JavaScript listeners. If a `NativeModule` is supplied to the constructor, it
@@ -36,8 +39,11 @@ export type {EventSubscription};
* This means event names must be globally unique, and it means that call sites
* can theoretically listen to `RCTDeviceEventEmitter` (although discouraged).
*/
export default class NativeEventEmitter<TEventToArgsMap: {...}>
implements IEventEmitter<TEventToArgsMap>
export default class NativeEventEmitter<
TEventToArgsMap: $ReadOnly<
Record<string, $ReadOnlyArray<UnsafeObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> implements IEventEmitter<TEventToArgsMap>
{
_nativeModule: ?NativeModule;
@@ -18,8 +18,9 @@ import RCTDeviceEventEmitter from '../RCTDeviceEventEmitter';
/**
* Mock `NativeEventEmitter` to ignore Native Modules.
*/
export default class NativeEventEmitter<TEventToArgsMap: {...}>
implements IEventEmitter<TEventToArgsMap>
export default class NativeEventEmitter<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<mixed>>>,
> implements IEventEmitter<TEventToArgsMap>
{
addListener<TEvent: $Keys<TEventToArgsMap>>(
eventType: TEvent,
@@ -4198,8 +4198,12 @@ exports[`public API should not change unintentionally Libraries/EventEmitter/Nat
removeListeners(count: number): void;
}
export type { EventSubscription };
declare export default class NativeEventEmitter<TEventToArgsMap: { ... }>
implements IEventEmitter<TEventToArgsMap>
type UnsafeObject = Object;
declare export default class NativeEventEmitter<
TEventToArgsMap: $ReadOnly<
Record<string, $ReadOnlyArray<UnsafeObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> implements IEventEmitter<TEventToArgsMap>
{
constructor(nativeModule: ?NativeModule): void;
addListener<TEvent: $Keys<TEventToArgsMap>>(
@@ -8801,10 +8805,13 @@ exports[`public API should not change unintentionally Libraries/vendor/core/Erro
`;
exports[`public API should not change unintentionally Libraries/vendor/emitter/EventEmitter.js 1`] = `
"export interface EventSubscription {
"type UnsafeObject = Object;
export interface EventSubscription {
remove(): void;
}
export interface IEventEmitter<TEventToArgsMap: { ... }> {
export interface IEventEmitter<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> {
addListener<TEvent: $Keys<TEventToArgsMap>>(
eventType: TEvent,
listener: (...args: TEventToArgsMap[TEvent]) => mixed,
@@ -8817,8 +8824,11 @@ export interface IEventEmitter<TEventToArgsMap: { ... }> {
removeAllListeners<TEvent: $Keys<TEventToArgsMap>>(eventType?: ?TEvent): void;
listenerCount<TEvent: $Keys<TEventToArgsMap>>(eventType: TEvent): number;
}
declare export default class EventEmitter<TEventToArgsMap: { ... }>
implements IEventEmitter<TEventToArgsMap>
declare export default class EventEmitter<
TEventToArgsMap: $ReadOnly<
Record<string, $ReadOnlyArray<UnsafeObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> implements IEventEmitter<TEventToArgsMap>
{
addListener<TEvent: $Keys<TEventToArgsMap>>(
eventType: TEvent,
@@ -8,11 +8,16 @@
* @format
*/
// $FlowFixMe[unclear-type] unclear type of events
type UnsafeObject = Object;
export interface EventSubscription {
remove(): void;
}
export interface IEventEmitter<TEventToArgsMap: {...}> {
export interface IEventEmitter<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> {
addListener<TEvent: $Keys<TEventToArgsMap>>(
eventType: TEvent,
listener: (...args: TEventToArgsMap[TEvent]) => mixed,
@@ -35,7 +40,9 @@ interface Registration<TArgs> {
+remove: () => void;
}
type Registry<TEventToArgsMap: {...}> = {
type Registry<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> = {
[K in keyof TEventToArgsMap]: Set<Registration<TEventToArgsMap[K]>>,
};
@@ -59,8 +66,11 @@ type Registry<TEventToArgsMap: {...}> = {
* emitter.emit('error', new Error('Resource not found'));
*
*/
export default class EventEmitter<TEventToArgsMap: {...}>
implements IEventEmitter<TEventToArgsMap>
export default class EventEmitter<
TEventToArgsMap: $ReadOnly<
Record<string, $ReadOnlyArray<UnsafeObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> implements IEventEmitter<TEventToArgsMap>
{
// $FlowFixMe[incompatible-type]
#registry: Registry<TEventToArgsMap> = {};
@@ -81,7 +91,7 @@ export default class EventEmitter<TEventToArgsMap: {...}>
}
const registrations = allocate<
TEventToArgsMap,
TEvent,
$Keys<TEventToArgsMap>,
TEventToArgsMap[TEvent],
>(this.#registry, eventType);
const registration: Registration<TEventToArgsMap[TEvent]> = {
@@ -136,20 +146,22 @@ export default class EventEmitter<TEventToArgsMap: {...}>
* Returns the number of registered listeners for the supplied event.
*/
listenerCount<TEvent: $Keys<TEventToArgsMap>>(eventType: TEvent): number {
const registrations: ?Set<Registration<mixed>> = this.#registry[eventType];
const registrations: ?Set<Registration<TEventToArgsMap[TEvent]>> =
this.#registry[eventType];
return registrations == null ? 0 : registrations.size;
}
}
function allocate<
TEventToArgsMap: {...},
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
TEvent: $Keys<TEventToArgsMap>,
TEventArgs: TEventToArgsMap[TEvent],
>(
registry: Registry<TEventToArgsMap>,
eventType: TEvent,
): Set<Registration<TEventArgs>> {
let registrations: ?Set<Registration<TEventArgs>> = registry[eventType];
): Set<Registration<TEventToArgsMap[TEvent]>> {
let registrations: ?Set<Registration<TEventToArgsMap[TEvent]>> =
registry[eventType];
if (registrations == null) {
registrations = new Set();
registry[eventType] = registrations;
+1
View File
@@ -33,6 +33,7 @@ const ENTRY_POINTS = [
'packages/react-native/Libraries/Settings/Settings.js',
'packages/react-native/Libraries/Performance/Systrace.js',
'packages/react-native/Libraries/LogBox/LogBox.js',
'packages/react-native/Libraries/vendor/emitter/EventEmitter.js',
];
/**