Merge pull request #31371 from pshrmn/react-generic-event

[react & react-native] Synthetic event types extend BaseSyntheticEvent
This commit is contained in:
Nathan Shively-Sanders
2018-12-21 09:17:13 -08:00
committed by GitHub
4 changed files with 43 additions and 56 deletions
+1 -17
View File
@@ -359,23 +359,7 @@ type TaskProvider = () => Task;
type NodeHandle = number;
// Similar to React.SyntheticEvent except for nativeEvent
export interface NativeSyntheticEvent<T> {
bubbles: boolean;
cancelable: boolean;
currentTarget: NodeHandle;
defaultPrevented: boolean;
eventPhase: number;
isTrusted: boolean;
nativeEvent: T;
isPropagationStopped(): boolean;
isDefaultPrevented(): boolean;
persist(): void;
preventDefault(): void;
stopPropagation(): void;
target: NodeHandle;
timeStamp: number;
type: string;
}
export interface NativeSyntheticEvent<T> extends React.BaseSyntheticEvent<T, NodeHandle, NodeHandle> {}
export interface NativeTouchEvent {
/**
+6
View File
@@ -203,6 +203,12 @@ const testNativeSyntheticEvent = <T extends {}>(e: NativeSyntheticEvent<T>): voi
e.nativeEvent;
}
function eventHandler<T extends React.BaseSyntheticEvent>(e: T) {}
function handler(e: GestureResponderEvent) {
eventHandler(e);
}
type ElementProps<C> = C extends React.Component<infer P, any> ? P : never;
class CustomView extends React.Component {
+27 -39
View File
@@ -19,6 +19,7 @@
// Martin Hochel <https://github.com/hotell>
// Frank Li <https://github.com/franklixuefei>
// Jessica Franco <https://github.com/Kovensky>
// Paul Sherman <https://github.com/pshrmn>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.8
@@ -905,51 +906,47 @@ declare namespace React {
//
// Event System
// ----------------------------------------------------------------------
interface SyntheticEvent<T = Element> {
// TODO: change any to unknown when moving to TS v3
interface BaseSyntheticEvent<E = object, C = any, T = any> {
nativeEvent: E;
currentTarget: C;
target: T;
bubbles: boolean;
/**
* A reference to the element on which the event listener is registered.
*/
currentTarget: EventTarget & T;
cancelable: boolean;
defaultPrevented: boolean;
eventPhase: number;
isTrusted: boolean;
nativeEvent: Event;
preventDefault(): void;
isDefaultPrevented(): boolean;
stopPropagation(): void;
isPropagationStopped(): boolean;
persist(): void;
// If you thought this should be `EventTarget & T`, see https://github.com/DefinitelyTyped/DefinitelyTyped/pull/12239
/**
* A reference to the element from which the event was originally dispatched.
* This might be a child element to the element on which the event listener is registered.
*
* @see currentTarget
*/
target: EventTarget;
timeStamp: number;
type: string;
}
interface ClipboardEvent<T = Element> extends SyntheticEvent<T> {
/**
* currentTarget - a reference to the element on which the event listener is registered.
*
* target - a reference to the element from which the event was originally dispatched.
* This might be a child element to the element on which the event listener is registered.
* If you thought this should be `EventTarget & T`, see https://github.com/DefinitelyTyped/DefinitelyTyped/pull/12239
*/
interface SyntheticEvent<T = Element, E = Event> extends BaseSyntheticEvent<E, EventTarget & T, EventTarget> {}
interface ClipboardEvent<T = Element> extends SyntheticEvent<T, NativeClipboardEvent> {
clipboardData: DataTransfer;
nativeEvent: NativeClipboardEvent;
}
interface CompositionEvent<T = Element> extends SyntheticEvent<T> {
interface CompositionEvent<T = Element> extends SyntheticEvent<T, NativeCompositionEvent> {
data: string;
nativeEvent: NativeCompositionEvent;
}
interface DragEvent<T = Element> extends MouseEvent<T> {
interface DragEvent<T = Element> extends MouseEvent<T, NativeDragEvent> {
dataTransfer: DataTransfer;
nativeEvent: NativeDragEvent;
}
interface PointerEvent<T = Element> extends MouseEvent<T> {
interface PointerEvent<T = Element> extends MouseEvent<T, NativePointerEvent> {
pointerId: number;
pressure: number;
tiltX: number;
@@ -958,11 +955,9 @@ declare namespace React {
height: number;
pointerType: 'mouse' | 'pen' | 'touch';
isPrimary: boolean;
nativeEvent: NativePointerEvent;
}
interface FocusEvent<T = Element> extends SyntheticEvent<T> {
nativeEvent: NativeFocusEvent;
interface FocusEvent<T = Element> extends SyntheticEvent<T, NativeFocusEvent> {
relatedTarget: EventTarget;
target: EventTarget & T;
}
@@ -979,7 +974,7 @@ declare namespace React {
target: EventTarget & T;
}
interface KeyboardEvent<T = Element> extends SyntheticEvent<T> {
interface KeyboardEvent<T = Element> extends SyntheticEvent<T, NativeKeyboardEvent> {
altKey: boolean;
charCode: number;
ctrlKey: boolean;
@@ -995,13 +990,12 @@ declare namespace React {
locale: string;
location: number;
metaKey: boolean;
nativeEvent: NativeKeyboardEvent;
repeat: boolean;
shiftKey: boolean;
which: number;
}
interface MouseEvent<T = Element> extends SyntheticEvent<T> {
interface MouseEvent<T = Element, E = NativeMouseEvent> extends SyntheticEvent<T, E> {
altKey: boolean;
button: number;
buttons: number;
@@ -1015,7 +1009,6 @@ declare namespace React {
metaKey: boolean;
movementX: number;
movementY: number;
nativeEvent: NativeMouseEvent;
pageX: number;
pageY: number;
relatedTarget: EventTarget;
@@ -1024,7 +1017,7 @@ declare namespace React {
shiftKey: boolean;
}
interface TouchEvent<T = Element> extends SyntheticEvent<T> {
interface TouchEvent<T = Element> extends SyntheticEvent<T, NativeTouchEvent> {
altKey: boolean;
changedTouches: TouchList;
ctrlKey: boolean;
@@ -1033,36 +1026,31 @@ declare namespace React {
*/
getModifierState(key: string): boolean;
metaKey: boolean;
nativeEvent: NativeTouchEvent;
shiftKey: boolean;
targetTouches: TouchList;
touches: TouchList;
}
interface UIEvent<T = Element> extends SyntheticEvent<T> {
interface UIEvent<T = Element> extends SyntheticEvent<T, NativeUIEvent> {
detail: number;
nativeEvent: NativeUIEvent;
view: AbstractView;
}
interface WheelEvent<T = Element> extends MouseEvent<T> {
interface WheelEvent<T = Element> extends MouseEvent<T, NativeWheelEvent> {
deltaMode: number;
deltaX: number;
deltaY: number;
deltaZ: number;
nativeEvent: NativeWheelEvent;
}
interface AnimationEvent<T = Element> extends SyntheticEvent<T> {
interface AnimationEvent<T = Element> extends SyntheticEvent<T, NativeAnimationEvent> {
animationName: string;
elapsedTime: number;
nativeEvent: NativeAnimationEvent;
pseudoElement: string;
}
interface TransitionEvent<T = Element> extends SyntheticEvent<T> {
interface TransitionEvent<T = Element> extends SyntheticEvent<T, NativeTransitionEvent> {
elapsedTime: number;
nativeEvent: NativeTransitionEvent;
propertyName: string;
pseudoElement: string;
}
+9
View File
@@ -695,6 +695,15 @@ React.createFactory(TransitionGroup)({ component: "div" });
const newObjShallow = update(obj, { $merge: { b: 6, c: 7 } }); // => {a: 5, b: 6, c: 7}
}
//
// Events
// --------------------------------------------------------------------------
function eventHandler<T extends React.BaseSyntheticEvent>(e: T) {}
function handler(e: React.MouseEvent) {
eventHandler(e);
}
//
// The SyntheticEvent.target.value should be accessible for onChange
// --------------------------------------------------------------------------