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

Improved compatibility with the upcoming @types/react for React 19 #3206

Merged
merged 19 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/curly-houses-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@emotion/styled': patch
'@emotion/react': patch
---

Improved compatibility with the upcoming `@types/react` for React 19 where the global `JSX` namespace doesn't exist anymore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
diff --git a/dist/lint.js b/dist/lint.js
index ae29f2a0936fe8e4dee9b4a607ed5c611872d30d..96746c55f2df24c6d09ee30ff85e404138ad0fbe 100644
--- a/dist/lint.js
+++ b/dist/lint.js
@@ -107,9 +107,9 @@ function startsWithDirectory(filePath, dirPath) {
return normalFilePath.startsWith(normalDirPath + "/") || normalFilePath.startsWith(normalDirPath + "\\");
}
function testNoTsIgnore(text) {
- const tsIgnore = "ts-ignore";
- const pos = text.indexOf(tsIgnore);
- return pos === -1 ? undefined : { pos, message: "'ts-ignore' is forbidden." };
+ // const tsIgnore = "ts-ignore";
+ // const pos = text.indexOf(tsIgnore);
+ // return pos === -1 ? undefined : { pos, message: "'ts-ignore' is forbidden." };
}
function testNoTslintDisables(text) {
const tslintDisable = "tslint:disable";
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@
"@testing-library/react": "13.0.0-alpha.5",
"@types/jest": "^29.5.12",
"@types/node": "^12.20.37",
"@types/react": "^18.0.9",
"@types/react": "18.2.6",
"@typescript-eslint/eslint-plugin": "^7.13.0",
"@typescript-eslint/parser": "^7.13.0",
"babel-check-duplicated-nodes": "^1.0.0",
Expand Down Expand Up @@ -239,5 +239,8 @@
"unified": "^6.1.6",
"webpack-bundle-analyzer": "3.3.2"
},
"packageManager": "yarn@3.2.3"
"packageManager": "yarn@3.2.3",
"resolutions": {
"@definitelytyped/dtslint@0.0.112": "patch:@definitelytyped/dtslint@npm%3A0.0.112#./.yarn/patches/@definitelytyped-dtslint-npm-0.0.112-1e6b842976.patch"
}
}
3 changes: 2 additions & 1 deletion packages/native/types/tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"no-null-undefined-union": false,
"no-unnecessary-generics": false,
"strict-export-declare-modifiers": false,
"unnecessary-bind": false
"unnecessary-bind": false,
"ban-ts-ignore": false
}
}
6 changes: 3 additions & 3 deletions packages/react/types/helper.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as React from 'react'
import { ReactJSX } from './jsx-namespace'

/**
* @desc Utility type for getting props type of React component.
* It takes `defaultProps` into an account - making props with defaults optional.
*/
export type PropsOf<
C extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
> = JSX.LibraryManagedAttributes<C, React.ComponentProps<C>>
C extends keyof ReactJSX.IntrinsicElements | React.JSXElementConstructor<any>
> = ReactJSX.LibraryManagedAttributes<C, React.ComponentProps<C>>

// We need to use this version of Omit as it's distributive (Will preserve unions)
export type DistributiveOmit<T, U> = T extends any
Expand Down
82 changes: 69 additions & 13 deletions packages/react/types/jsx-namespace.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,81 @@ import 'react'
import { Interpolation } from '@emotion/serialize'
import { Theme } from '@emotion/react'

type IsPreReact19 = 2 extends Parameters<React.FunctionComponent<any>>['length']
? true
: false

type WithConditionalCSSProp<P> = 'className' extends keyof P
? string extends P['className' & keyof P]
? { css?: Interpolation<Theme> }
: {}
: {}

// unpack all here to avoid infinite self-referencing when defining our own JSX namespace
type ReactJSXElement = JSX.Element
type ReactJSXElementClass = JSX.ElementClass
type ReactJSXElementAttributesProperty = JSX.ElementAttributesProperty
type ReactJSXElementChildrenAttribute = JSX.ElementChildrenAttribute
type ReactJSXLibraryManagedAttributes<C, P> = JSX.LibraryManagedAttributes<C, P>
type ReactJSXIntrinsicAttributes = JSX.IntrinsicAttributes
type ReactJSXIntrinsicClassAttributes<T> = JSX.IntrinsicClassAttributes<T>
type ReactJSXIntrinsicElements = JSX.IntrinsicElements

// based on the code from @types/react@18.2.8
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/3197efc097d522c4bf02b94e1a0766d007d6cdeb/types/react/index.d.ts#LL3204C13-L3204C13
type ReactJSXElementType = string | React.JSXElementConstructor<any>
// unpack all here to avoid infinite self-referencing when defining our own JSX namespace for the pre-React 19 case
type ReactJSXElement = true extends IsPreReact19
? /** @ts-ignore */
JSX.Element
: /** @ts-ignore */
React.JSX.Element
type ReactJSXElementClass = true extends IsPreReact19
? /** @ts-ignore */
JSX.ElementClass
: /** @ts-ignore */
React.JSX.ElementClass
type ReactJSXElementAttributesProperty = true extends IsPreReact19
? /** @ts-ignore */
JSX.ElementAttributesProperty
: /** @ts-ignore */
React.JSX.ElementAttributesProperty
type ReactJSXElementChildrenAttribute = true extends IsPreReact19
? /** @ts-ignore */
JSX.ElementChildrenAttribute
: /** @ts-ignore */
React.JSX.ElementChildrenAttribute
type ReactJSXLibraryManagedAttributes<C, P> = true extends IsPreReact19
? /** @ts-ignore */
JSX.LibraryManagedAttributes<C, P>
: /** @ts-ignore */
React.JSX.LibraryManagedAttributes<C, P>
type ReactJSXIntrinsicAttributes = true extends IsPreReact19
? /** @ts-ignore */
JSX.IntrinsicAttributes
: /** @ts-ignore */
React.JSX.IntrinsicAttributes
type ReactJSXIntrinsicClassAttributes<T> = true extends IsPreReact19
? /** @ts-ignore */
JSX.IntrinsicClassAttributes<T>
: /** @ts-ignore */
React.JSX.IntrinsicClassAttributes<T>
type ReactJSXIntrinsicElements = true extends IsPreReact19
? /** @ts-ignore */
JSX.IntrinsicElements
: /** @ts-ignore */
React.JSX.IntrinsicElements

type ReactJSXElementType = true extends IsPreReact19
? // based on the code from @types/react@18.2.8
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/3197efc097d522c4bf02b94e1a0766d007d6cdeb/types/react/index.d.ts#LL3204C13-L3204C13
string | React.JSXElementConstructor<any>
: /** @ts-ignore */
React.JSX.ElementType

export namespace ReactJSX {
type ElementType = ReactJSXElementType
interface Element extends ReactJSXElement {}
interface ElementClass extends ReactJSXElementClass {}
interface ElementAttributesProperty
extends ReactJSXElementAttributesProperty {}
interface ElementChildrenAttribute extends ReactJSXElementChildrenAttribute {}

type LibraryManagedAttributes<C, P> = ReactJSXLibraryManagedAttributes<C, P>

interface IntrinsicAttributes extends ReactJSXIntrinsicAttributes {}
interface IntrinsicClassAttributes<T>
extends ReactJSXIntrinsicClassAttributes<T> {}

type IntrinsicElements = ReactJSXIntrinsicElements
}

export namespace EmotionJSX {
type ElementType = ReactJSXElementType
Expand Down
3 changes: 2 additions & 1 deletion packages/react/types/tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"no-unnecessary-generics": false,
"no-empty-interface": false,
"strict-export-declare-modifiers": false,
"unnecessary-bind": false
"unnecessary-bind": false,
"ban-ts-ignore": false
}
}
24 changes: 14 additions & 10 deletions packages/styled/types/base.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import * as React from 'react'
import { ComponentSelector, Interpolation } from '@emotion/serialize'
import { PropsOf, Theme } from '@emotion/react'
import { ReactJSXIntrinsicElements } from './jsx-namespace'

export {
ArrayInterpolation,
Expand Down Expand Up @@ -49,9 +50,9 @@ export interface StyledComponent<
withComponent<C extends React.ComponentType<React.ComponentProps<C>>>(
component: C
): StyledComponent<ComponentProps & PropsOf<C>>
withComponent<Tag extends keyof JSX.IntrinsicElements>(
withComponent<Tag extends keyof ReactJSXIntrinsicElements>(
tag: Tag
): StyledComponent<ComponentProps, JSX.IntrinsicElements[Tag]>
): StyledComponent<ComponentProps, ReactJSXIntrinsicElements[Tag]>
}

/**
Expand Down Expand Up @@ -169,23 +170,26 @@ export interface CreateStyled {
>

<
Tag extends keyof JSX.IntrinsicElements,
ForwardedProps extends keyof JSX.IntrinsicElements[Tag] &
string = keyof JSX.IntrinsicElements[Tag] & string
Tag extends keyof ReactJSXIntrinsicElements,
ForwardedProps extends keyof ReactJSXIntrinsicElements[Tag] &
string = keyof ReactJSXIntrinsicElements[Tag] & string
>(
tag: Tag,
options: FilteringStyledOptions<JSX.IntrinsicElements[Tag], ForwardedProps>
options: FilteringStyledOptions<
ReactJSXIntrinsicElements[Tag],
ForwardedProps
>
): CreateStyledComponent<
{ theme?: Theme; as?: React.ElementType },
Pick<JSX.IntrinsicElements[Tag], ForwardedProps>
Pick<ReactJSXIntrinsicElements[Tag], ForwardedProps>
>

<Tag extends keyof JSX.IntrinsicElements>(
<Tag extends keyof ReactJSXIntrinsicElements>(
tag: Tag,
options?: StyledOptions<JSX.IntrinsicElements[Tag]>
options?: StyledOptions<ReactJSXIntrinsicElements[Tag]>
): CreateStyledComponent<
{ theme?: Theme; as?: React.ElementType },
JSX.IntrinsicElements[Tag]
ReactJSXIntrinsicElements[Tag]
>
}

Expand Down
5 changes: 3 additions & 2 deletions packages/styled/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { Theme } from '@emotion/react'
import { CreateStyled as BaseCreateStyled, CreateStyledComponent } from './base'
import { ReactJSXIntrinsicElements } from './jsx-namespace'

export {
ArrayInterpolation,
Expand All @@ -17,12 +18,12 @@ export {
} from './base'

export type StyledTags = {
[Tag in keyof JSX.IntrinsicElements]: CreateStyledComponent<
[Tag in keyof ReactJSXIntrinsicElements]: CreateStyledComponent<
{
theme?: Theme
as?: React.ElementType
},
JSX.IntrinsicElements[Tag]
ReactJSXIntrinsicElements[Tag]
>
}

Expand Down
14 changes: 14 additions & 0 deletions packages/styled/types/jsx-namespace.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// this is basically a slimmed down copy of https://github.com/emotion-js/emotion/blob/main/packages/react/types/jsx-namespace.d.ts
// it helps to avoid issues when combining newer `@emotion/styled` and older `@emotion/react` versions
// in such setup, ReactJSX namespace won't exist in `@emotion/react` and that would lead to errors
import 'react'

type IsPreReact19 = 2 extends Parameters<React.FunctionComponent<any>>['length']
? true
: false

export type ReactJSXIntrinsicElements = true extends IsPreReact19
? /** @ts-ignore */
JSX.IntrinsicElements
: /** @ts-ignore */
React.JSX.IntrinsicElements
2 changes: 1 addition & 1 deletion packages/styled/types/tests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const Container3 = styled.div(({ theme }) => ({
const Box = styled('div', {
shouldForwardProp: (
propName
): propName is Exclude<keyof JSX.IntrinsicElements['div'], 'color'> =>
): propName is Exclude<keyof React.JSX.IntrinsicElements['div'], 'color'> =>
propName !== 'color'
})<{ color: Array<string> }>(props => ({
color: props.color[0]
Expand Down
5 changes: 4 additions & 1 deletion packages/styled/types/tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"check-preblock"
],
"no-unnecessary-generics": false,
"unnecessary-bind": false
"unnecessary-bind": false,
"ban-ts-ignore": false,
"no-empty-interface": false,
"strict-export-declare-modifiers": false
}
}
2 changes: 1 addition & 1 deletion site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@types/js-yaml": "^4.0.5",
"@types/node": "^12.20.37",
"@types/prismjs": "^1.26.0",
"@types/react": "^18.0.9",
"@types/react": "18.2.6",
"@types/remark-prism": "^1.3.3",
"facepaint": "^1.2.1",
"gray-matter": "^4.0.3",
Expand Down
33 changes: 27 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2580,6 +2580,27 @@ __metadata:
languageName: node
linkType: hard

"@definitelytyped/dtslint@patch:@definitelytyped/dtslint@npm%3A0.0.112#./.yarn/patches/@definitelytyped-dtslint-npm-0.0.112-1e6b842976.patch::locator=emotion-monorepo%40workspace%3A.":
version: 0.0.112
resolution: "@definitelytyped/dtslint@patch:@definitelytyped/dtslint@npm%3A0.0.112#./.yarn/patches/@definitelytyped-dtslint-npm-0.0.112-1e6b842976.patch::version=0.0.112&hash=753776&locator=emotion-monorepo%40workspace%3A."
dependencies:
"@definitelytyped/dts-critic": ^0.0.112
"@definitelytyped/header-parser": ^0.0.112
"@definitelytyped/typescript-versions": ^0.0.112
"@definitelytyped/utils": ^0.0.112
fs-extra: ^6.0.1
json-stable-stringify: ^1.0.1
strip-json-comments: ^2.0.1
tslint: 5.14.0
yargs: ^15.1.0
peerDependencies:
typescript: ">= 3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.7.0-dev || >= 3.8.0-dev || >= 3.9.0-dev || >= 4.0.0-dev"
bin:
dtslint: dist/index.js
checksum: 531e55134c34b4be44bd5aedb193b5dd99c098a374d1725e53bfc567a6bad8da6d314a7446f1480b2502afc6ed579555b4a8b31c40513f68dc7e679b51784c5f
languageName: node
linkType: hard

"@definitelytyped/header-parser@npm:^0.0.112":
version: 0.0.112
resolution: "@definitelytyped/header-parser@npm:0.0.112"
Expand Down Expand Up @@ -6354,14 +6375,14 @@ __metadata:
languageName: node
linkType: hard

"@types/react@npm:*, @types/react@npm:>=16, @types/react@npm:^18.0.9":
version: 18.0.14
resolution: "@types/react@npm:18.0.14"
"@types/react@npm:*, @types/react@npm:18.2.6, @types/react@npm:>=16":
version: 18.2.6
resolution: "@types/react@npm:18.2.6"
dependencies:
"@types/prop-types": "*"
"@types/scheduler": "*"
csstype: ^3.0.2
checksum: 608eb57a383eedc54c79949673e5e8314f6b0c61542bff58721c8c47a18c23e2832e77c656050c2c2c004b62cf25582136c7c56fe1b6263a285c065fae31dbcf
checksum: dea9d232d8df7ac357367a69dcb557711ab3d5501807ffa77cebeee73d49ee94d095f298e36853c63ed47cce097eee4c7eae2aaa8c02fac3f0171ec1b523a819
languageName: node
linkType: hard

Expand Down Expand Up @@ -12617,7 +12638,7 @@ __metadata:
"@testing-library/react": 13.0.0-alpha.5
"@types/jest": ^29.5.12
"@types/node": ^12.20.37
"@types/react": ^18.0.9
"@types/react": 18.2.6
"@typescript-eslint/eslint-plugin": ^7.13.0
"@typescript-eslint/parser": ^7.13.0
babel-check-duplicated-nodes: ^1.0.0
Expand Down Expand Up @@ -12689,7 +12710,7 @@ __metadata:
"@types/js-yaml": ^4.0.5
"@types/node": ^12.20.37
"@types/prismjs": ^1.26.0
"@types/react": ^18.0.9
"@types/react": 18.2.6
"@types/remark-prism": ^1.3.3
facepaint: ^1.2.1
gray-matter: ^4.0.3
Expand Down
Loading