Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to properly alias Preact/compat with TypeScript? #2150

Closed
talentlessguy opened this issue Nov 25, 2019 · 17 comments
Closed

How to properly alias Preact/compat with TypeScript? #2150

talentlessguy opened this issue Nov 25, 2019 · 17 comments

Comments

@talentlessguy
Copy link

Reproducing

  1. git clone https://github.com/talentlessguy/preact-emotion-ts.git
  2. yarn install
  3. Open vscode, with these settings:
{
    "eslint.packageManager": "yarn",
    "npm.packageManager": "yarn",
    "editor.formatOnSave": true,
    "typescript.updateImportsOnFileMove.enabled": "always",
    "editor.suggestSelection": "first",
    "eslint.autoFixOnSave": true,
    "eslint.alwaysShowStatus": true,
    "prettier.configPath": "/home/v1rtl/.prettierrc.yml",
    "[typescriptreact]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    }

And see this error on <Header> component:

JSX element type 'Header' does not have any construct or call signatures.

Versions

emotion: 10.0.22
preact: 10.0.5
eslint: 6.7
typescript: 3.7.2

Screenshot

image

The weirdiest thing is that npx eslint doesn't show anything like this

preact-emotion-ts is 📦 v1.0.0 via ⬢ v13.2.0 
❯ npx eslint src/*.tsx --fix
Warning: React version was set to "detect" in eslint-plugin-react settings, but the "react" package is not installed. Assuming latest React version for linting.

I don't what the issue is coming from but I suppose it is a problem with typings of preact (?)

@JoviDeCroock
Copy link
Member

JoviDeCroock commented Nov 25, 2019

The reason behind npx eslint src/*.tsx --fix not reporting this is because it is a tsc (the process that compiles typescript) error, this means that the typescript compiler is throwing this and isn't related to linting.

@talentlessguy
Copy link
Author

The reason behind npx eslint src/*.tsx --fix not reporting this is because it is a tsc (the process that compiles typescript) error, this means that the typescript compiler is throwing this and isn't related to linting.

okay, thanks for pointing out the issue.

npx tsc outputs this:

❯ npx tsc
node_modules/@emotion/core/types/index.d.ts:17:8 - error TS2307: Cannot find module 'react'.

17 } from 'react'
          ~~~~~~~

node_modules/@emotion/styled-base/types/helper.d.ts:1:24 - error TS2307: Cannot find module 'react'.

1 import * as React from 'react'
                         ~~~~~~~

node_modules/@emotion/styled-base/types/helper.d.ts:7:23 - error TS2694: Namespace 'global.JSX' has no exported member 'IntrinsicElements'.

7   C extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
                        ~~~~~~~~~~~~~~~~~

node_modules/@emotion/styled-base/types/helper.d.ts:8:9 - error TS2694: Namespace 'global.JSX' has no exported member 'LibraryManagedAttributes'.

8 > = JSX.LibraryManagedAttributes<C, React.ComponentPropsWithRef<C>>
          ~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@emotion/styled-base/types/index.d.ts:16:24 - error TS2307: Cannot find module 'react'.

16 import * as React from 'react'
                          ~~~~~~~

node_modules/@emotion/styled-base/types/index.d.ts:29:20 - error TS2694: Namespace 'global.JSX' has no exported member 'IntrinsicElements'.

29 type JSXInEl = JSX.IntrinsicElements
                      ~~~~~~~~~~~~~~~~~

src/index.tsx:23:6 - error TS2604: JSX element type 'Header' does not have any construct or call signatures.

23     <Header>Hello World</Header>
        ~~~~~~


Found 7 errors.

@JoviDeCroock
Copy link
Member

This seems to be related to us missing the deprecated SFC shorthand in /compat/src/index.d.ts

@talentlessguy
Copy link
Author

But I don't use preact/compat 🤔

If there is no any option with using pure Preact and Emotion, I can alias it

@JoviDeCroock
Copy link
Member

The purpose of preact/compat is allowing you to use React libraries in Preact. Emotion is written for React

@talentlessguy
Copy link
Author

@JoviDeCroock okay, then I'll just stick to preact/compat

Closing the issue

@talentlessguy
Copy link
Author

Update: Even when aliasing to preact/compat in tsconfig.json, like this:

{
  "compilerOptions": {
    "outDir": "./dist",
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "es6",
    "moduleResolution": "node",
    "target": "es6",
    "jsx": "react",
    "baseUrl": ".",
    "paths": {
      "react": ["node_modules/preact/compat"],
      "react-dom": ["node_modules/preact/compat"]
    },
    "allowSyntheticDefaultImports": true
  },
  "include": ["./src/**/*"]
}

I still get this error (and new ones):

❯ npx tsc
node_modules/@emotion/core/types/index.d.ts:8:3 - error TS2305: Module '"../../../preact/compat/src"' has no exported member 'ClassAttributes'.

// ...

node_modules/@emotion/styled-base/types/index.d.ts:29:20 - error TS2694: Namespace 'global.JSX' has no exported member 'IntrinsicElements'.

src/index.tsx:23:6 - error TS2604: JSX element type 'Header' does not have any construct or call signatures.

Found 18 errors.

Full log here: https://termbin.com/r9vr

I guess I messed up somewhere in aliasing

@talentlessguy talentlessguy reopened this Nov 25, 2019
@talentlessguy talentlessguy changed the title Using Preact with Emotion and TypeScript produces a typing warning in VS Code How to properly alias Preact with TypeScript? Nov 25, 2019
@talentlessguy talentlessguy changed the title How to properly alias Preact with TypeScript? How to properly alias Preact/compat with TypeScript? Nov 25, 2019
@JoviDeCroock
Copy link
Member

Your tsconfig is excluding paths from taking effect in node_modules, since it's set to only include source files.

Secondly to make parcel work you'll have to add

  "alias": {
    "react": "preact/compat",
    "react-dom": "preact/compat"
  }

To package.json since parcel will try to resolve react

@talentlessguy
Copy link
Author

okay, I removed module resolution from tsconfig.json

yeah, I have it aliased, so it builds fine (using npx parcel index.html), but in VS Code editor warning is still present

JSX element type 'Header' does not have any construct or call signatures.

@JoviDeCroock
Copy link
Member

JoviDeCroock commented Nov 25, 2019

okay, I removed module resolution from tsconfig.json

Well that's not really the solution, it goes recursively into @emotion but paths has no effect there due to the scoping settings you have in include. So it will just try React instead of your resolution. Can't look into it right now but if you haven't solved it when I get home I'll take a look.

@talentlessguy
Copy link
Author

@JoviDeCroock no problem, I can wait

Thanks for spending time on my issue btw ❤️

@ForsakenHarmony
Copy link
Member

I just remembered I used emotion at some point

https://github.com/ForsakenHarmony/sky1/blob/master/frontend/typings/react/index.d.ts
I have react aliased with preact exports

@talentlessguy
Copy link
Author

talentlessguy commented Nov 26, 2019

@ForsakenHarmony thanks, it works now!

my final react.d.ts is like this:

import {
  AnyComponent,
  createElement,
  FunctionalComponent,
  RenderableProps,
  ComponentChild
} from 'preact'

export {
  Attributes,
  FunctionalComponent as SFC,
  AnyComponent as ComponentType,
  AnyComponent as JSXElementConstructor,
  Component as ComponentClass,
  ClassAttributes,
  PreactContext as Context,
  PreactProvider as Provider,
  VNode as ReactElement,
  VNode as ReactNode,
  createElement,
  Fragment,
  Ref,
  render,
  JSX,
  RenderableProps as ComponentPropsWithRef
} from 'preact'

// export type JSXElementConstructor = AnyComponent;

there are only 3 warnings about JSX namespace but VS Code doesn't complain about them:

node_modules/@emotion/styled-base/types/helper.d.ts:7:19 - error TS2503: Cannot find namespace 'JSX'.

7   C extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
                    ~~~

node_modules/@emotion/styled-base/types/helper.d.ts:8:5 - error TS2503: Cannot find namespace 'JSX'.

8 > = JSX.LibraryManagedAttributes<C, React.ComponentPropsWithRef<C>>
      ~~~

node_modules/@emotion/styled-base/types/index.d.ts:29:16 - error TS2503: Cannot find namespace 'JSX'.

29 type JSXInEl = JSX.IntrinsicElements
                  ~~~


Found 3 errors.

Closing the issue 👍

@ahuglajbclajep
Copy link

ahuglajbclajep commented Apr 28, 2020

As for e.target, since JSX.TargetedEvent is declared with type, it seems that the type definition can not be overridden and existing React code must be changed.
See also #1930 and #2084 (comment).

@matthias-ccri
Copy link

matthias-ccri commented Apr 27, 2021

For ReactNode I have ComponentChild instead of VNode.

Because according to @types/react, ReactNode includes string etc. But VNode is an object.

export {
    ...
    ComponentChild as ReactNode,
    // Also:
    Component as PureComponent,
    ...
} from 'preact';

For the record, this is how to use the react.d.ts file, in your tsconfig.json:

"paths": {
  "react": ["react.d.ts"],
},

@piotr-cz
Copy link

piotr-cz commented Jul 6, 2021

I had similar problems when compiling tsx because on of the dependencies - react-leaflet uses react types extensively.

I was successful with a modified version of @types/react (without the JSX namespace), but then decided to just set "skipLibCheck": false in tsconfig.json as described in docs

@mate-h
Copy link

mate-h commented Nov 12, 2021

@talentlessguy Small correction:

react.d.ts

import {
  AnyComponent,
  createElement,
  FunctionalComponent,
  RenderableProps,
  ComponentChild,
  ComponentChildren
} from 'preact'

export {
  Attributes,
  FunctionalComponent as SFC,
  AnyComponent as ComponentType,
  AnyComponent as JSXElementConstructor,
  Component as ComponentClass,
  ClassAttributes,
  PreactContext as Context,
  PreactProvider as Provider,
  VNode as ReactElement,
  createElement,
  Fragment,
  Ref,
  render,
  JSX,
  RenderableProps as ComponentPropsWithRef
} from 'preact'

export type ReactNode = ComponentChild | ComponentChildren;

// export type JSXElementConstructor = AnyComponent;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants