ant-design / antd-style

css-in-js library with antd v5 token system
https://ant-design.github.io/antd-style/
MIT License
224 stars 35 forks source link

🐛[BUG] TypeScript: ThemeProvider type alias is returning the wrong type #163

Open overthemike opened 2 months ago

overthemike commented 2 months ago

🐛 bug description

ThemeProvider is currently expecting a return type of React.ReactNode when it should be using JSX.Element. I was creating an HOC for ThemeProvider so that I could keep customToken object in it's own file. ThemeProvider has it's return type as ReactNode which allows for undefined which causes typescript to yell at you. I was able to get rid of the error by overriding the type alias to instead return JSX.Element, which doesn't allow for returning undefined.

📷 Steps to reproduce

import { ReactNode } from 'react'
import { ThemeProvider, ThemeProviderProps } from 'antd-style'

interface NewToken {}

const customTokenValues = {}

declare module 'antd-style' {
  export interface CustomToken extends NewToken {}
}

type MyThemeProviderType = ({
  children
}: {
  children: ReactNode
}) => ReactNode

export const MyThemeProvider: MyThemeProviderType = ({ children }) => (
  <ThemeProvider customToken={customTokenValues}> {/* typescript throws an error here */}
  {/*
  'ThemeProvider' cannot be used as a JSX component.
   Its return type 'ReactNode' is not a valid JSX element.
   Type 'undefined' is not assignable to type 'Element | null'.
  */}
    {children}
  </ThemeProvider>
)

I was able to fix it by overriding ThemeProvider's typeAlias and changing the return type from ReactNode to JSX.Element

import { ReactNode } from 'react'
import { ThemeProvider, ThemeProviderProps } from 'antd-style'

interface NewToken {}

const customTokenValues = {}

declare module 'antd-style' {
  export interface CustomToken extends NewToken {}
}

type MyThemeProviderType = ({
  children
}: {
  children: ReactNode
}) => ReactNode

const ThemeProviderComponent = ThemeProvider as (<T = any, S = any>(props: ThemeProviderProps<T, S>) => JSX.Element)

export const MyThemeProvider: MyThemeProviderType = ({ children }) => (
  <ThemeProviderComponent customToken={customTokenValues}>
    {children}
  </ThemeProviderComponent>
)

🏞 Expected results

No errors when trying to use an HOC on ThemeProvider

💻 Reproduce code

All is listed above

© Version information

arvinxx commented 2 months ago

ReactNode is the standard type in React 18. What's your ts and react version?

arvinxx commented 2 months ago

refs:

overthemike commented 2 months ago

ReactNode is the standard type in React 18. What's your ts and react version?

I see. Sorry for the duplicate ticket. I'm using React 17 still. Typescript is at 4.6.3. I think it would be a good idea to add a warning to the documentation about this issue along with a workaround for users that are on older versions of React / TS. I'd be happy to put in a PR for that if it's ok to have English in the docs as well.

arvinxx commented 2 months ago

@overthemike yeah, PR welcome~