Skip to content

Commit fe40530

Browse files
committed
refactor: improve types for nodes in callbacks
1 parent 03e348f commit fe40530

File tree

5 files changed

+47
-36
lines changed

5 files changed

+47
-36
lines changed

src/CSSTransition.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ class CSSTransition extends React.Component<Props> {
243243
exit: {},
244244
};
245245

246-
onEnter = (maybeNode: HTMLElement, maybeAppearing?: boolean) => {
246+
onEnter = (maybeNode: HTMLElement | boolean, maybeAppearing?: boolean) => {
247247
const [node, appearing] = this.resolveArguments(maybeNode, maybeAppearing);
248248
this.removeClasses(node, 'exit');
249249
this.addClass(node, appearing ? 'appear' : 'enter', 'base');
@@ -253,7 +253,7 @@ class CSSTransition extends React.Component<Props> {
253253
}
254254
};
255255

256-
onEntering = (maybeNode: HTMLElement, maybeAppearing?: boolean) => {
256+
onEntering = (maybeNode: HTMLElement | boolean, maybeAppearing?: boolean) => {
257257
const [node, appearing] = this.resolveArguments(maybeNode, maybeAppearing);
258258
const type = appearing ? 'appear' : 'enter';
259259
this.addClass(node, type, 'active');
@@ -263,7 +263,7 @@ class CSSTransition extends React.Component<Props> {
263263
}
264264
};
265265

266-
onEntered = (maybeNode: HTMLElement, maybeAppearing?: boolean) => {
266+
onEntered = (maybeNode: HTMLElement | boolean, maybeAppearing?: boolean) => {
267267
const [node, appearing] = this.resolveArguments(maybeNode, maybeAppearing);
268268
const type = appearing ? 'appear' : 'enter';
269269
this.removeClasses(node, type);
@@ -274,7 +274,7 @@ class CSSTransition extends React.Component<Props> {
274274
}
275275
};
276276

277-
onExit = (maybeNode: HTMLElement) => {
277+
onExit = (maybeNode?: HTMLElement) => {
278278
const [node] = this.resolveArguments(maybeNode);
279279
this.removeClasses(node, 'appear');
280280
this.removeClasses(node, 'enter');
@@ -285,7 +285,7 @@ class CSSTransition extends React.Component<Props> {
285285
}
286286
};
287287

288-
onExiting = (maybeNode: HTMLElement) => {
288+
onExiting = (maybeNode?: HTMLElement) => {
289289
const [node] = this.resolveArguments(maybeNode);
290290
this.addClass(node, 'exit', 'active');
291291

@@ -294,7 +294,7 @@ class CSSTransition extends React.Component<Props> {
294294
}
295295
};
296296

297-
onExited = (maybeNode: HTMLElement) => {
297+
onExited = (maybeNode?: HTMLElement) => {
298298
const [node] = this.resolveArguments(maybeNode);
299299
this.removeClasses(node, 'exit');
300300
this.addClass(node, 'exit', 'done');
@@ -306,9 +306,10 @@ class CSSTransition extends React.Component<Props> {
306306

307307
// when prop `nodeRef` is provided `node` is excluded
308308
resolveArguments = (
309-
maybeNode: HTMLElement,
309+
maybeNode: HTMLElement | boolean | undefined,
310310
maybeAppearing?: boolean
311-
): [HTMLElement | null, HTMLElement | null | boolean | undefined] =>
311+
): [HTMLElement, boolean] =>
312+
// @ts-expect-error FIXME: Type at position 1 in source is not compatible with type at position 1 in target. Type 'boolean | HTMLElement' is not assignable to type 'boolean'. Type 'HTMLElement' is not assignable to type 'boolean'.ts(2322)
312313
this.props.nodeRef
313314
? [this.props.nodeRef.current, maybeNode] // here `maybeNode` is actually `appearing`
314315
: [maybeNode, maybeAppearing]; // `findDOMNode` was used

src/ReplaceTransition.tsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import ReactDOM from 'react-dom';
55
import TransitionGroup from './TransitionGroup';
66
import type { Props as TransitionProps } from './Transition';
77

8-
type Props = TransitionProps & {
8+
type Props = Omit<TransitionProps, 'children'> & {
99
children: [ReactElement<TransitionProps>, ReactElement<TransitionProps>];
1010
};
1111

@@ -41,33 +41,37 @@ class ReplaceTransition extends React.Component<Props> {
4141
},
4242
};
4343

44-
handleEnter = (...args: any[]) => this.handleLifecycle('onEnter', 0, args);
45-
handleEntering = (...args: any[]) =>
44+
handleEnter = (...args: [HTMLElement | boolean, boolean | undefined]) =>
45+
this.handleLifecycle('onEnter', 0, args);
46+
handleEntering = (...args: [HTMLElement | boolean, boolean | undefined]) =>
4647
this.handleLifecycle('onEntering', 0, args);
47-
handleEntered = (...args: any[]) =>
48+
handleEntered = (...args: [HTMLElement | boolean, boolean | undefined]) =>
4849
this.handleLifecycle('onEntered', 0, args);
4950

50-
handleExit = (...args: any[]) => this.handleLifecycle('onExit', 1, args);
51-
handleExiting = (...args: any[]) =>
51+
handleExit = (...args: [HTMLElement | boolean, boolean | undefined]) =>
52+
this.handleLifecycle('onExit', 1, args);
53+
handleExiting = (...args: [HTMLElement | boolean, boolean | undefined]) =>
5254
this.handleLifecycle('onExiting', 1, args);
53-
handleExited = (...args: any[]) => this.handleLifecycle('onExited', 1, args);
55+
handleExited = (...args: [HTMLElement | boolean, boolean | undefined]) =>
56+
this.handleLifecycle('onExited', 1, args);
5457

5558
handleLifecycle(
5659
handler: LifecycleMethodNames,
5760
idx: number,
58-
originalArgs: any[]
61+
originalArgs: [HTMLElement | boolean, boolean | undefined]
5962
) {
6063
const { children } = this.props;
6164
// @ts-expect-error FIXME: Type 'string' is not assignable to type 'ReactElement<Props, string | JSXElementConstructor<any>>'.ts(2322)
6265
const child: ReactElement<TransitionProps> =
6366
React.Children.toArray(children)[idx];
6467

65-
// @ts-expect-error FIXME: A spread argument must either have a tuple type or be passed to a rest parameter.ts(2556)
68+
// @ts-expect-error FIXME: Type 'false' is not assignable to type '(((boolean | HTMLElement) & (HTMLElement | undefined)) & (HTMLElement | undefined)) & (HTMLElement | undefined)'.ts(2345)
6669
if (child.props[handler]) child.props[handler](...originalArgs);
6770
if (this.props[handler]) {
6871
const maybeNode = child.props.nodeRef
6972
? undefined
7073
: ReactDOM.findDOMNode(this);
74+
// FIXME: This type is inconsistent with on*** methods in Transition
7175
// @ts-expect-error FIXME: Argument of type 'Element | Text | null | undefined' is not assignable to parameter of type 'HTMLElement'.ts(2769)
7276
this.props[handler](maybeNode);
7377
}

src/Transition.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type TransitionState =
2222

2323
export type Props = {
2424
nodeRef?: RefObject<HTMLElement>;
25+
// The childProps argument is not documented
2526
children: (state: TransitionState, childProps: any) => ReactNode;
2627
in: boolean;
2728
mountOnEnter: boolean;
@@ -30,13 +31,13 @@ export type Props = {
3031
enter: boolean;
3132
exit: boolean;
3233
timeout: number | { appear?: number; enter?: number; exit?: number };
33-
addEndListener: (node: HTMLElement, done: boolean) => void;
34-
onEnter: (node: HTMLElement, isAppearing?: boolean) => void;
35-
onEntering: (node: HTMLElement, isAppearing?: boolean) => void;
36-
onEntered: (node: HTMLElement, isAppearing?: boolean) => void;
37-
onExit: (node: HTMLElement) => void;
38-
onExiting: (node: HTMLElement) => void;
39-
onExited: (node: HTMLElement) => void;
34+
addEndListener: (node: HTMLElement | undefined, done: boolean) => void;
35+
onEnter: (maybeNode: HTMLElement | boolean, isAppearing?: boolean) => void;
36+
onEntering: (maybeNode: HTMLElement | boolean, isAppearing?: boolean) => void;
37+
onEntered: (maybeNode: HTMLElement | boolean, isAppearing?: boolean) => void;
38+
onExit: (node?: HTMLElement) => void;
39+
onExiting: (node?: HTMLElement) => void;
40+
onExited: (node?: HTMLElement) => void;
4041
};
4142

4243
type State = {
@@ -513,8 +514,8 @@ class Transition extends React.Component<Props, State> {
513514
performExit() {
514515
const { exit } = this.props;
515516
const timeouts = this.getTimeouts();
516-
// FIXME
517-
const maybeNode: any = this.props.nodeRef
517+
// @ts-expect-error FIXME: Type 'Element | Text | null | undefined' is not assignable to type 'HTMLElement | undefined' Type 'null' is not assignable to type 'HTMLElement | undefined'.ts(2322)
518+
const maybeNode: HTMLElement | undefined = this.props.nodeRef
518519
? undefined
519520
: ReactDOM.findDOMNode(this);
520521

@@ -554,15 +555,15 @@ class Transition extends React.Component<Props, State> {
554555
this.setState(nextState, callback);
555556
}
556557

557-
setNextCallback(callback: (event: any) => void) {
558+
setNextCallback(callback: () => void) {
558559
let active = true;
559560

560-
this.nextCallback = (event: any) => {
561+
this.nextCallback = () => {
561562
if (active) {
562563
active = false;
563564
this.nextCallback = null;
564565

565-
callback(event);
566+
callback();
566567
}
567568
};
568569

src/TransitionGroup.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import PropTypes from 'prop-types';
2-
import React, { ReactNode } from 'react';
3-
import type { ReactElement } from 'react';
2+
import React from 'react';
3+
import type { ReactElement, ReactChild } from 'react';
44
import TransitionGroupContext from './TransitionGroupContext';
55

66
import {
@@ -28,7 +28,7 @@ type Props = {
2828
};
2929

3030
type State = {
31-
children: ReactNode[];
31+
children: Record<string, ReactChild>;
3232
contextValue: { isMounting: boolean };
3333
handleExited: (
3434
child: ReactElement<{ onExited: (node: HTMLElement) => void }>,
@@ -138,7 +138,7 @@ class TransitionGroup extends React.Component<Props, State> {
138138

139139
static getDerivedStateFromProps(
140140
nextProps: Props,
141-
{ children: prevChildMapping, handleExited, firstRender }: any
141+
{ children: prevChildMapping, handleExited, firstRender }: State
142142
) {
143143
return {
144144
children: firstRender
@@ -164,7 +164,6 @@ class TransitionGroup extends React.Component<Props, State> {
164164
this.setState((state) => {
165165
let children = { ...state.children };
166166
if (child.key) {
167-
// @ts-expect-error FIXME: Element implicitly has an 'any' type because index expression is not of type 'number'.ts(7015)
168167
delete children[child.key];
169168
}
170169
return { children };

src/utils/ChildMapping.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ function getProp(
100100

101101
export function getInitialChildMapping(
102102
props: { children: ReactNode[] },
103-
onExited: (child: ReactChild) => void
103+
onExited: (
104+
child: ReactElement<{ onExited: (node: HTMLElement) => void }>,
105+
node: HTMLElement
106+
) => void
104107
) {
105108
return getChildMapping(props.children, (child: ReactElement) => {
106109
return cloneElement(child, {
@@ -116,7 +119,10 @@ export function getInitialChildMapping(
116119
export function getNextChildMapping(
117120
nextProps: { children: ReactNode[] },
118121
prevChildMapping: Record<string, ReactChild>,
119-
onExited: (child: ReactChild) => void
122+
onExited: (
123+
child: ReactElement<{ onExited: (node: HTMLElement) => void }>,
124+
node: HTMLElement
125+
) => void
120126
) {
121127
let nextChildMapping = getChildMapping(nextProps.children);
122128
let children = mergeChildMappings(prevChildMapping, nextChildMapping);

0 commit comments

Comments
 (0)