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

feat(eslint-config): typescript-eslint 8 #1326

Merged
merged 11 commits into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from 8 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
2 changes: 1 addition & 1 deletion configs/eslint-config/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default [
'@typescript-eslint/no-unsafe-member-access': 'warn',
'@typescript-eslint/no-floating-promises': 'warn',
'@typescript-eslint/no-unsafe-call': 'warn',
'@typescript-eslint/no-throw-literal': 'warn',
'@typescript-eslint/only-throw-error': 'warn',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @typescript-eslint plugin does not have a no-throw-literal rule. Instead, I replaced it with @typescript-eslint/only-throw-error, which enforces the same rule.

'@typescript-eslint/no-confusing-void-expression': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/no-empty-function': 'warn',
Expand Down
2 changes: 1 addition & 1 deletion configs/eslint-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react-compiler": "0.0.0-experimental-9aef357-20240815",
"eslint-plugin-react-hooks": "^4.6.2",
"typescript-eslint": "^7.18.0"
"typescript-eslint": "^8.9.0"
},
"devDependencies": {
"@suspensive/tsconfig": "workspace:*"
Expand Down
8 changes: 4 additions & 4 deletions configs/eslint-config/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
'@typescript-eslint/no-unsafe-member-access': 'warn',
'@typescript-eslint/no-floating-promises': 'warn',
'@typescript-eslint/no-unsafe-call': 'warn',
'@typescript-eslint/no-throw-literal': 'warn',
'@typescript-eslint/only-throw-error': 'warn',
'@typescript-eslint/no-confusing-void-expression': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/no-empty-function': 'warn',
Expand All @@ -94,10 +94,10 @@
rules: vitest.configs.recommended.rules,
settings: { vitest: { typecheck: true } },
},
jestDom.configs['flat/recommended'] as unknown as ReturnType<typeof tseslint.config>[number],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beautiful..❤️

jestDom.configs['flat/recommended'],

Check warning on line 97 in configs/eslint-config/src/index.ts

View workflow job for this annotation

GitHub Actions / Check quality (ci:eslint)

Unsafe member access .configs on an `error` typed value
{
plugins: {
import: importPlugin,

Check warning on line 100 in configs/eslint-config/src/index.ts

View workflow job for this annotation

GitHub Actions / Check quality (ci:eslint)

Unsafe assignment of an error typed value
},
rules: {
'sort-imports': ['error', { ignoreDeclarationSort: true }],
Expand All @@ -113,20 +113,20 @@
],
},
},
eslintPluginPrettierRecommended as unknown as ReturnType<typeof tseslint.config>[number]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy..❤️

eslintPluginPrettierRecommended
)

export const suspensiveReactTypeScriptConfig: ReturnType<typeof tseslint.config> = tseslint.config(
...suspensiveTypeScriptConfig,
{
files: ['**/*.{ts,tsx}'],
...(pluginReact.configs.recommended as unknown as ReturnType<typeof tseslint.config>[number]),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So cool...❤️

...pluginReact.configs.recommended,
ignores: ['**/*.mdx/**/*.{ts,tsx}'],
},
{
plugins: {
'react-hooks': reactHooks.configs.recommended,

Check warning on line 128 in configs/eslint-config/src/index.ts

View workflow job for this annotation

GitHub Actions / Check quality (ci:eslint)

Unsafe assignment of an error typed value

Check warning on line 128 in configs/eslint-config/src/index.ts

View workflow job for this annotation

GitHub Actions / Check quality (ci:eslint)

Unsafe member access .configs on an `error` typed value
'react-compiler': reactCompiler,

Check warning on line 129 in configs/eslint-config/src/index.ts

View workflow job for this annotation

GitHub Actions / Check quality (ci:eslint)

Unsafe assignment of an error typed value
},
languageOptions: {
globals: {
Expand All @@ -146,7 +146,7 @@

export const suspensiveNextTypeScriptConfig: ReturnType<typeof tseslint.config> = [
...suspensiveReactTypeScriptConfig,
{ plugins: { 'plugin:@next/next/recommended': next.configs.recommended } },

Check warning on line 149 in configs/eslint-config/src/index.ts

View workflow job for this annotation

GitHub Actions / Check quality (ci:eslint)

Unsafe assignment of an error typed value

Check warning on line 149 in configs/eslint-config/src/index.ts

View workflow job for this annotation

GitHub Actions / Check quality (ci:eslint)

Unsafe member access .configs on an `error` typed value
]

export const suspensiveMDXConfig: Linter.Config[] = [
Expand Down
3 changes: 2 additions & 1 deletion configs/tsconfig/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"preserveWatchOutput": true,
"skipLibCheck": true,
"strict": true,
"resolveJsonModule": true
"resolveJsonModule": true,
"allowJs": true
Copy link
Contributor Author

@SEOKKAMONI SEOKKAMONI Oct 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0:0  error  Parsing error: "parserOptions.project" has been provided for @typescript-eslint/parser. The file was not found in any of the provided project(s): eslint.config.mjs

By default, tsconfig does not include .js files. This behavior caused the error:
"The file was not found in any of the provided project(s): eslint.config.mjs."
We resolved this issue by adding allowJs: true, which made it possible to treat .js files as part of the project.

https://typescript-eslint.io/troubleshooting/typed-linting#i-get-errors-telling-me--was-not-found-by-the-project-service-consider-either-including-it-in-the-tsconfigjson-or-including-it-in-allowdefaultproject

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are .js file extensions in tseslint.configs.strictTypeChecked. Could this be the reason for the parsing error?

Copy link
Collaborator

@kangju2000 kangju2000 Oct 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if the purpose of ESLint is to lint only TypeScript files. If that's the case, couldn't we remove the .js extensions from the scripts?

-"ci:eslint": "eslint \"**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts}\"",
+"ci:eslint": "eslint \"**/*.{ts,tsx,cts,mts}\"",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I respect your opinion, and I believe that excluding checks for .js files in ESLint settings might be a somewhat regrettable choice. ESLint provides various rules that help maintain code conventions, and these rules still hold significant meaning for files that do not use TypeScript. For example, rules like import/order and prettier can greatly enhance code readability and maintain consistency within the project. From this perspective, I think it is more desirable to apply ESLint checks to all files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are .js file extensions in tseslint.configs.strictTypeChecked. Could this be the reason for the parsing error?

If we remove the .js extension from tseslint.configs.strictTypeChecked, the error will disappear, but this means that ESLint will not be applied to JavaScript files at all, which I think is not an ideal solution.

Copy link
Member

@manudeli manudeli Oct 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to follow this problem as @kangju2000 way. I agree both opinion by you guys, but I see this error and I couldn't resolve it during quite long time! so I made this commit 8408867
Could you make new Pull Request if you want to check js,jsx,mjs,cjs at that time?

image

},
"exclude": ["dist", "esm", "build", "node_modules"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
const [isClicked, setIsClicked] = useState(false)
return (
<>
<button onClick={() => setIsClicked(true)}>click to render</button>

Check warning on line 9 in examples/vite-react-18-suspense-prerender-siblings-problem/src/App.tsx

View workflow job for this annotation

GitHub Actions / Check quality (ci:eslint)

Add missing 'type' attribute on 'button' component
{isClicked ? (
<Suspense fallback={<Fallback />}>
{Array.from({ length: 10 }, (_, i) => (
Expand Down Expand Up @@ -50,6 +50,7 @@
queryKey: ['dummy', ms],
queryFn: async () => {
console.log({ fetch: `fetch${ms + 1}` })
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return fetch(`https://dummyjson.com/users/${ms + 1}`).then((res) => res.json())
},
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
"noFallthroughCasesInSwitch": true,
"allowJs": true
},
"include": ["src", "eslint.config.mjs", "vite.config.ts"]
}
3 changes: 3 additions & 0 deletions knip.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
"packages/react-native": {
"ignoreDependencies": ["expo", "ts-node"],
"ignore": ["babel.config.cjs"]
},
"packages/react-dom": {
"ignoreDependencies": ["react-dom", "@types/react-dom"]
}
}
}
42 changes: 24 additions & 18 deletions packages/jotai/src/Atom.test-d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,72 +15,78 @@ const loadableAtom = loadable(asyncAtom)

describe('<Atom/>', () => {
it('type check', () => {
;() => (
;(() => (
<Atom atom={countAtom}>
{(result) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const returnOfJotai = useAtom(countAtom)
expectTypeOf(result).toEqualTypeOf<typeof returnOfJotai>()
return <></>
}}
</Atom>
)
;() => (
))()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool

;(() => (
<Atom atom={readOnlyCountAtom}>
{(result) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const returnOfJotai = useAtom(readOnlyCountAtom)
expectTypeOf(result).toEqualTypeOf<typeof returnOfJotai>()
return <></>
}}
</Atom>
)
;() => (
))()
;(() => (
<Atom atom={writeOnlyCountAtom}>
{(result) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const returnOfJotai = useAtom(writeOnlyCountAtom)
expectTypeOf(result).toEqualTypeOf<typeof returnOfJotai>()
return <></>
}}
</Atom>
)
;() => (
))()
;(() => (
<Atom atom={asyncAtom}>
{(result) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const returnOfJotai = useAtom(asyncAtom)
expectTypeOf(result).toEqualTypeOf<typeof returnOfJotai>()
return <></>
}}
</Atom>
)
;() => (
))()
;(() => (
<Atom atom={asyncIncrementAtom}>
{(result) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const returnOfJotai = useAtom(asyncIncrementAtom)
expectTypeOf(result).toEqualTypeOf<typeof returnOfJotai>()
return <></>
}}
</Atom>
)
;() => (
))()
;(() => (
<Atom atom={loadableAtom}>
{(result) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const returnOfJotai = useAtom(loadableAtom)
expectTypeOf(result).toEqualTypeOf<typeof returnOfJotai>()
return <></>
}}
</Atom>
)
))()

expectTypeOf(<Atom atom={countAtom}>{() => <></>}</Atom>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<Atom atom={countAtom}>{() => <></>}</Atom>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<Atom atom={countAtom}>{() => <></>}</Atom>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<Atom atom={readOnlyCountAtom}>{() => <></>}</Atom>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<Atom atom={readOnlyCountAtom}>{() => <></>}</Atom>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<Atom atom={readOnlyCountAtom}>{() => <></>}</Atom>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<Atom atom={writeOnlyCountAtom}>{() => <></>}</Atom>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<Atom atom={writeOnlyCountAtom}>{() => <></>}</Atom>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<Atom atom={writeOnlyCountAtom}>{() => <></>}</Atom>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<Atom atom={asyncAtom}>{() => <></>}</Atom>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<Atom atom={asyncAtom}>{() => <></>}</Atom>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<Atom atom={asyncAtom}>{() => <></>}</Atom>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<Atom atom={asyncIncrementAtom}>{() => <></>}</Atom>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<Atom atom={asyncIncrementAtom}>{() => <></>}</Atom>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<Atom atom={asyncIncrementAtom}>{() => <></>}</Atom>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<Atom atom={loadableAtom}>{() => <></>}</Atom>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<Atom atom={loadableAtom}>{() => <></>}</Atom>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<Atom atom={loadableAtom}>{() => <></>}</Atom>).not.toEqualTypeOf<ReactNode>()
})
})
42 changes: 24 additions & 18 deletions packages/jotai/src/AtomValue.test-d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,72 +15,78 @@ const loadableAtom = loadable(asyncAtom)

describe('<AtomValue/>', () => {
it('type check', () => {
;() => (
;(() => (
<AtomValue atom={countAtom}>
{(value) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const valueOfJotai = useAtomValue(countAtom)
expectTypeOf(value).toEqualTypeOf<typeof valueOfJotai>()
return <></>
}}
</AtomValue>
)
;() => (
))()
;(() => (
<AtomValue atom={readOnlyCountAtom}>
{(value) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const valueOfJotai = useAtomValue(readOnlyCountAtom)
expectTypeOf(value).toEqualTypeOf<typeof valueOfJotai>()
return <></>
}}
</AtomValue>
)
;() => (
))()
;(() => (
<AtomValue atom={writeOnlyCountAtom}>
{(value) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const valueOfJotai = useAtomValue(writeOnlyCountAtom)
expectTypeOf(value).toEqualTypeOf<typeof valueOfJotai>()
return <></>
}}
</AtomValue>
)
;() => (
))()
;(() => (
<AtomValue atom={asyncAtom}>
{(value) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const valueOfJotai = useAtomValue(asyncAtom)
expectTypeOf(value).toEqualTypeOf<typeof valueOfJotai>()
return <></>
}}
</AtomValue>
)
;() => (
))()
;(() => (
<AtomValue atom={asyncIncrementAtom}>
{(value) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const valueOfJotai = useAtomValue(asyncIncrementAtom)
expectTypeOf(value).toEqualTypeOf<typeof valueOfJotai>()
return <></>
}}
</AtomValue>
)
;() => (
))()
;(() => (
<AtomValue atom={loadableAtom}>
{(value) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const valueOfJotai = useAtomValue(loadableAtom)
expectTypeOf(value).toEqualTypeOf<typeof valueOfJotai>()
return <></>
}}
</AtomValue>
)
))()

expectTypeOf(<AtomValue atom={countAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<AtomValue atom={countAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<AtomValue atom={countAtom}>{() => <></>}</AtomValue>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<AtomValue atom={readOnlyCountAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<AtomValue atom={readOnlyCountAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<AtomValue atom={readOnlyCountAtom}>{() => <></>}</AtomValue>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<AtomValue atom={writeOnlyCountAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<AtomValue atom={writeOnlyCountAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<AtomValue atom={writeOnlyCountAtom}>{() => <></>}</AtomValue>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<AtomValue atom={asyncAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<AtomValue atom={asyncAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<AtomValue atom={asyncAtom}>{() => <></>}</AtomValue>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<AtomValue atom={asyncIncrementAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<AtomValue atom={asyncIncrementAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<AtomValue atom={asyncIncrementAtom}>{() => <></>}</AtomValue>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<AtomValue atom={loadableAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<AtomValue atom={loadableAtom}>{() => <></>}</AtomValue>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<AtomValue atom={loadableAtom}>{() => <></>}</AtomValue>).not.toEqualTypeOf<ReactNode>()
})
})
21 changes: 12 additions & 9 deletions packages/jotai/src/SetAtom.test-d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,42 @@ const asyncIncrementAtom = atom(null, async (get, set) => {

describe('<SetAtom/>', () => {
it('type check', () => {
;() => (
;(() => (
<SetAtom atom={countAtom}>
{(value) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const valueOfJotai = useSetAtom(countAtom)
expectTypeOf(value).toEqualTypeOf<typeof valueOfJotai>()
return <></>
}}
</SetAtom>
)
;() => (
))()
;(() => (
<SetAtom atom={writeOnlyCountAtom}>
{(value) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const valueOfJotai = useSetAtom(writeOnlyCountAtom)
expectTypeOf(value).toEqualTypeOf<typeof valueOfJotai>()
return <></>
}}
</SetAtom>
)
;() => (
))()
;(() => (
<SetAtom atom={asyncIncrementAtom}>
{(value) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const valueOfJotai = useSetAtom(asyncIncrementAtom)
expectTypeOf(value).toEqualTypeOf<typeof valueOfJotai>()
return <></>
}}
</SetAtom>
)
))()

expectTypeOf(<SetAtom atom={countAtom}>{() => <></>}</SetAtom>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<SetAtom atom={countAtom}>{() => <></>}</SetAtom>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<SetAtom atom={countAtom}>{() => <></>}</SetAtom>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<SetAtom atom={writeOnlyCountAtom}>{() => <></>}</SetAtom>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<SetAtom atom={writeOnlyCountAtom}>{() => <></>}</SetAtom>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<SetAtom atom={writeOnlyCountAtom}>{() => <></>}</SetAtom>).not.toEqualTypeOf<ReactNode>()
expectTypeOf(<SetAtom atom={asyncIncrementAtom}>{() => <></>}</SetAtom>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<SetAtom atom={asyncIncrementAtom}>{() => <></>}</SetAtom>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<SetAtom atom={asyncIncrementAtom}>{() => <></>}</SetAtom>).not.toEqualTypeOf<ReactNode>()
})
})
5 changes: 1 addition & 4 deletions packages/react-dom/src/test-utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as React from 'react'
import * as DeprecatedReactTestUtils from 'react-dom/test-utils'
import { act } from 'react'

declare global {
// eslint-disable-next-line no-var
Expand All @@ -8,8 +7,6 @@ declare global {
var jest: { fn: typeof vi.fn } | undefined
}

const act = typeof React.act === 'function' ? React.act : DeprecatedReactTestUtils.act

type Item = {
callback: IntersectionObserverCallback
elements: Set<Element>
Expand Down
6 changes: 3 additions & 3 deletions packages/react-query-4/src/Mutation.test-d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ const mutationFn = () => Promise.resolve(5)

describe('<Mutation/>', () => {
it('type check', () => {
;() => (
;(() => (
<Mutation mutationFn={mutationFn}>
{(mutation) => {
expectTypeOf(mutation).toEqualTypeOf<UseMutationResult<number, unknown, void>>()
return <></>
}}
</Mutation>
)
))()

expectTypeOf(<Mutation mutationFn={mutationFn}>{() => <></>}</Mutation>).toEqualTypeOf<JSX.Element>()
expectTypeOf(<Mutation mutationFn={mutationFn}>{() => <></>}</Mutation>).toEqualTypeOf<React.JSX.Element>()
expectTypeOf(<Mutation mutationFn={mutationFn}>{() => <></>}</Mutation>).not.toEqualTypeOf<ReactNode>()
})
})
Loading
Loading