Skip to content

Commit 9414e3c

Browse files
mattmccutchenjohnnyreilly
authored andcommitted
react, react-dom: Enable strictFunctionTypes. (DefinitelyTyped#30748)
Fixes https://stackoverflow.com/q/53298949 .
1 parent c8b8c10 commit 9414e3c

File tree

7 files changed

+29
-17
lines changed

7 files changed

+29
-17
lines changed

types/react-addons-test-utils/index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,11 @@ declare namespace TestUtils {
160160
root: Component<any>,
161161
tagName: string): Element;
162162

163-
export function scryRenderedComponentsWithType<T extends Component<{}>, C extends ComponentClass<{}>>(
163+
export function scryRenderedComponentsWithType<T extends Component<any>, C extends ComponentClass<any>>(
164164
root: Component<any>,
165165
type: ClassType<any, T, C>): T[];
166166

167-
export function findRenderedComponentWithType<T extends Component<{}>, C extends ComponentClass<{}>>(
167+
export function findRenderedComponentWithType<T extends Component<any>, C extends ComponentClass<any>>(
168168
root: Component<any>,
169169
type: ClassType<any, T, C>): T;
170170

types/react-dom/react-dom-tests.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as ReactTestUtils from 'react-dom/test-utils';
77
declare function describe(desc: string, f: () => void): void;
88
declare function it(desc: string, f: () => void): void;
99

10-
class TestComponent extends React.Component { }
10+
class TestComponent extends React.Component<{x: string}> { }
1111

1212
describe('ReactDOM', () => {
1313
it('render', () => {

types/react-dom/test-utils/index.d.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export interface SyntheticEventData extends OptionalEventProperties {
5959
export type EventSimulator = (element: Element | Component<any>, eventData?: SyntheticEventData) => void;
6060

6161
export interface MockedComponentClass {
62-
new (props: {}): any;
62+
new (props: any): any;
6363
}
6464

6565
export interface ShallowRenderer {
@@ -160,8 +160,12 @@ export function renderIntoDocument<T extends Element>(
160160
element: DOMElement<any, T>): T;
161161
export function renderIntoDocument(
162162
element: SFCElement<any>): void;
163-
export function renderIntoDocument<T extends Component<any>>(
164-
element: CElement<any, T>): T;
163+
// If we replace `P` with `any` in this overload, then some tests fail because
164+
// calls to `renderIntoDocument` choose the last overload on the
165+
// subtype-relation pass and get an undesirably broad return type. Using `P`
166+
// allows this overload to match on the subtype-relation pass.
167+
export function renderIntoDocument<P, T extends Component<P>>(
168+
element: CElement<P, T>): T;
165169
export function renderIntoDocument<P>(
166170
element: ReactElement<P>): Component<P> | Element | void;
167171

@@ -257,7 +261,7 @@ export function findRenderedDOMComponentWithTag(
257261
/**
258262
* Finds all instances of components with type equal to `componentClass`.
259263
*/
260-
export function scryRenderedComponentsWithType<T extends Component, C extends ComponentClass>(
264+
export function scryRenderedComponentsWithType<T extends Component<any>, C extends ComponentClass<any>>(
261265
root: Component<any>,
262266
type: ClassType<any, T, C>): T[];
263267

@@ -266,7 +270,7 @@ export function scryRenderedComponentsWithType<T extends Component, C extends Co
266270
* and returns that one result, or throws exception if there is any other
267271
* number of matches besides one.
268272
*/
269-
export function findRenderedComponentWithType<T extends Component, C extends ComponentClass>(
273+
export function findRenderedComponentWithType<T extends Component<any>, C extends ComponentClass<any>>(
270274
root: Component<any>,
271275
type: ClassType<any, T, C>): T;
272276

types/react-dom/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"noImplicitAny": true,
1616
"noImplicitThis": true,
1717
"strictNullChecks": false,
18-
"strictFunctionTypes": false,
18+
"strictFunctionTypes": true,
1919
"baseUrl": "../",
2020
"typeRoots": [
2121
"../"

types/react/index.d.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,7 @@ declare namespace React {
492492
*/
493493
type ClassType<P, T extends Component<P, ComponentState>, C extends ComponentClass<P>> =
494494
C &
495-
(new (props: P, context?: any) => T) &
496-
(new (props: P, context?: any) => { props: P });
495+
(new (props: P, context?: any) => T);
497496

498497
//
499498
// Component Specs and Lifecycle

types/react/test/index.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ const props: Props & React.ClassAttributes<any> = {
4949
foo: 42
5050
};
5151

52+
const scProps: SCProps = {
53+
foo: 42
54+
};
55+
5256
declare const container: Element;
5357

5458
//
@@ -258,9 +262,9 @@ const domFactoryElement: React.DOMElement<React.DOMAttributes<{}>, Element> =
258262
const element: React.CElement<Props, ModernComponent> = React.createElement(ModernComponent, props);
259263
const elementNoState: React.CElement<Props, ModernComponentNoState> = React.createElement(ModernComponentNoState, props);
260264
const elementNullProps: React.CElement<{}, ModernComponentNoPropsAndState> = React.createElement(ModernComponentNoPropsAndState, null);
261-
const functionComponentElement: React.FunctionComponentElement<SCProps> = React.createElement(FunctionComponent, props);
265+
const functionComponentElement: React.FunctionComponentElement<SCProps> = React.createElement(FunctionComponent, scProps);
262266
const functionComponentElementNullProps: React.FunctionComponentElement<SCProps> = React.createElement(FunctionComponent4, null);
263-
const legacyStatelessComponentElement: React.SFCElement<SCProps> = React.createElement(FunctionComponent, props);
267+
const legacyStatelessComponentElement: React.SFCElement<SCProps> = React.createElement(FunctionComponent, scProps);
264268
const legacyStatelessComponentElementNullProps: React.SFCElement<SCProps> = React.createElement(FunctionComponent4, null);
265269
const domElement: React.DOMElement<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> = React.createElement("div");
266270
const domElementNullProps = React.createElement("div", null);
@@ -393,7 +397,12 @@ const ForwardingRefComponent = React.forwardRef((props: {}, ref: React.Ref<RefCo
393397

394398
function RefCarryingComponent() {
395399
const ref: React.RefObject<RefComponent> = React.createRef();
396-
return React.createElement(ForwardingRefComponent, { ref });
400+
// Without the explicit type argument, TypeScript infers `{ref: React.RefObject<RefComponent>}`
401+
// from the second argument because both of the inferences generated by the first argument
402+
// (both to the `P` in the call signature and the `P` in `defaultProps`) have low priority.
403+
// Then we get a type error because `ForwardingRefComponent.defaultProps` has the wrong type.
404+
// Can/should this be fixed somehow?
405+
return React.createElement<React.RefAttributes<RefComponent>>(ForwardingRefComponent, { ref });
397406
}
398407

399408
//
@@ -633,11 +642,11 @@ const foundComponents: ModernComponent[] = TestUtils.scryRenderedComponentsWithT
633642

634643
// ReactTestUtils custom type guards
635644

636-
const emptyElement1: React.ReactElement<{}> = React.createElement(ModernComponent);
645+
const emptyElement1: React.ReactElement<Props> = React.createElement(ModernComponent);
637646
if (TestUtils.isElementOfType(emptyElement1, FunctionComponent)) {
638647
emptyElement1.props.foo;
639648
}
640-
const emptyElement2: React.ReactElement<{}> = React.createElement(FunctionComponent);
649+
const emptyElement2: React.ReactElement<SCProps> = React.createElement(FunctionComponent);
641650
if (TestUtils.isElementOfType(emptyElement2, FunctionComponent)) {
642651
emptyElement2.props.foo;
643652
}

types/react/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"noImplicitAny": true,
1616
"noImplicitThis": false,
1717
"strictNullChecks": true,
18-
"strictFunctionTypes": false,
18+
"strictFunctionTypes": true,
1919
"baseUrl": "../",
2020
"typeRoots": [
2121
"../"

0 commit comments

Comments
 (0)