Esri/react-arcgis

Typescript error

Closed this issue · 5 comments

I've got an existing React app (built in Typescript) and when I install this component, my project will no longer build and yields a rather (to me at least) unhelpful error around ReactElement<P, T>. Weirdly, the build error occurs even if I'm not importing the module anywhere. The map will render ever so briefly but then the app will dump me to an error screen once Typescript has done its thing.
Is this some issue on my end or the esri-react end?

My setup:

  • Existing app with CRA
  • React 16.8.6
  • Typescript 3.3.4000

Reproduce:

  • Just npm install @esri/react-arcgis

My code:

import React, { useEffect, useRef, useState } from 'react';
import { Container } from 'reactstrap';
// tslint:disable-next-line: no-var-requires
require('../../sass/PGRFMap.scss');
import { Map } from '@esri/react-arcgis';
import * as ReactDOM from 'react-dom';

const PGRFMap: React.FC = () => {
    const viewDiv = useRef(null);

    useEffect(() => {
        ReactDOM.render(<Map />, viewDiv.current);
    }, [viewDiv]);

    return (
        <Container fluid className="h-100 p-0 m-0 fixed-top">
            <div id="viewDiv" ref={viewDiv} />
        </Container>
    );
};

export default PGRFMap;

Error:

TypeScript error: Type 'T' does not satisfy the constraint 'string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)'.
  Type 'string | number | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)' is not assignable to type 'string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)'.
    Type 'number' is not assignable to type 'string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)'.
      Type 'T' is not assignable to type 'string'.
        Type 'string | number | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)' is not assignable to type 'string'.
          Type 'number' is not assignable to type 'string'.  TS2344

     98 |         T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>,
     99 |         P = Pick<ComponentProps<T>, Exclude<keyof ComponentProps<T>, 'key' | 'ref'>>
  > 100 |     > extends ReactElement<P, T> { }
        |                               ^
    101 | 
    102 |     /**
    103 |      * @deprecated Please use `FunctionComponentElement`

Further investigation and it looks like this comes down to the js api typings. Specifically:

declare namespace JSX {
  interface IntrinsicElements {
    [elementName: string]: any;
  }

  interface Element {}
}

I commented out those lines from the typings and things seem to work at least insofar as I can now add a map and a few widgets but I haven't tested this yet with custom widgets or anything.

This also caused us a lot of trouble today. The issue is that the React type definitions also define JSX.IntrinsicElements and reference this interface as a type constraint on other types using the keyof operation: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5e15d96323a7d5cc7c2961453ea8d39eff1b38c6/types/react/index.d.ts#L106 and keyof { [elementName: string]: any;} will result in string | number not just string because of how js auto coerces numeric keys to strings. This type def string | number is then not compatible with other type constraints in the React's type defs which assume keyof JSX.IntrinsicElements will just be string as it is based on their own implementation of the JSX.IntrinsicElements interface: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5e15d96323a7d5cc7c2961453ea8d39eff1b38c6/types/react/index.d.ts#L2828

Thank you for the detailed explanation @gpartida.

I should have mentioned this to @tcatkins99 before, but if this really is an issue w/ the ArcGIS API types, it belongs over at https://github.com/Esri/jsapi-resources/issues, so I've gone ahead and opened Esri/jsapi-resources#188

If there is any specific action to be taken in this repo, please let me know.

Closing this in favor of Esri/jsapi-resources#188