From 77e22c40b6a0bb949e411e7e2ec26c70433c94f2 Mon Sep 17 00:00:00 2001 From: Marco Pasqualetti <24919330+marcalexiei@users.noreply.github.com> Date: Sun, 22 Dec 2024 12:08:21 +0100 Subject: [PATCH] refactor: enable typescript-eslint strict rules (#243) --- .gitignore | 2 ++ .../table-of-content/table-of-content.tsx | 4 ++- .../src/components/theme-btn/theme-btn.tsx | 4 +-- eslint.config.js | 34 ++++++++++++------- .../src/build-route-config.ts | 2 +- .../fs-router-vite-plugin/src/generator.ts | 15 ++++---- .../router/src/components/RouteMatch.spec.tsx | 2 +- packages/router/src/dynamic.tsx | 10 +++--- packages/router/src/hooks/useRoute.spec.tsx | 2 +- packages/router/src/hooks/useRouter.tsx | 2 +- packages/router/src/hooks/useRouterStore.tsx | 4 ++- .../router/src/hooks/useServerSideProps.tsx | 2 +- packages/router/src/route.ts | 2 +- packages/router/src/router.ts | 2 -- packages/tuono/src/ssr/index.tsx | 2 +- .../tuono/src/ssr/polyfills/messageChannel.ts | 4 ++- 16 files changed, 57 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index 31b0626e..10ff7e3d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ dist/ examples/*/pnpm-lock.yaml +vite.config.ts.timestamp* + ## Rust related ignores # Generated by Cargo diff --git a/apps/documentation/src/components/table-of-content/table-of-content.tsx b/apps/documentation/src/components/table-of-content/table-of-content.tsx index cebb5977..bdba5877 100644 --- a/apps/documentation/src/components/table-of-content/table-of-content.tsx +++ b/apps/documentation/src/components/table-of-content/table-of-content.tsx @@ -64,7 +64,9 @@ export function TableOfContents({ ), ) window.addEventListener('scroll', handleScroll) - return (): void => window.removeEventListener('scroll', handleScroll) + return (): void => { + window.removeEventListener('scroll', handleScroll) + } }, [router.pathname]) if (filteredHeadings.length === 0) { diff --git a/apps/documentation/src/components/theme-btn/theme-btn.tsx b/apps/documentation/src/components/theme-btn/theme-btn.tsx index a6217c74..3a9b9cc2 100644 --- a/apps/documentation/src/components/theme-btn/theme-btn.tsx +++ b/apps/documentation/src/components/theme-btn/theme-btn.tsx @@ -17,9 +17,9 @@ export default function ThemeBtn(): JSX.Element { return ( + onClick={() => { setColorScheme(computedColorScheme === 'light' ? 'dark' : 'light') - } + }} variant="default" size="lg" aria-label="Toggle color scheme" diff --git a/eslint.config.js b/eslint.config.js index 3849278a..d7647ab9 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -25,10 +25,17 @@ export default tseslint.config( reportUnusedDisableDirectives: 'error', }, }, + eslint.configs.recommended, + + /* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access */ eslintPluginImport.flatConfigs.recommended, eslintPluginImport.flatConfigs.typescript, - tseslint.configs.recommendedTypeChecked, + /* eslint-enable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access */ + + // eslint-disable-next-line import/no-named-as-default-member + tseslint.configs.strictTypeChecked, + { languageOptions: { parserOptions: { @@ -50,16 +57,13 @@ export default tseslint.config( rules: { // #region @typescript-eslint '@typescript-eslint/array-type': ['error', { default: 'generic' }], - '@typescript-eslint/no-wrapper-object-types': 'error', - '@typescript-eslint/no-empty-object-type': 'error', - '@typescript-eslint/no-unsafe-function-type': 'error', - '@typescript-eslint/ban-ts-comment': 'error', '@typescript-eslint/consistent-type-definitions': 'error', '@typescript-eslint/consistent-type-imports': [ 'error', { prefer: 'type-imports' }, ], '@typescript-eslint/explicit-module-boundary-types': 'error', + '@typescript-eslint/explicit-function-return-type': 'error', '@typescript-eslint/method-signature-style': ['error', 'property'], '@typescript-eslint/naming-convention': [ 'error', @@ -74,19 +78,24 @@ export default tseslint.config( }, }, ], - '@typescript-eslint/no-deprecated': 'error', '@typescript-eslint/no-empty-function': 'error', '@typescript-eslint/no-empty-interface': 'error', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-non-null-assertion': 'error', - '@typescript-eslint/no-unnecessary-condition': 'error', - '@typescript-eslint/no-unnecessary-type-assertion': 'error', - '@typescript-eslint/no-unused-vars': 'error', - '@typescript-eslint/explicit-function-return-type': 'error', + '@typescript-eslint/no-inferrable-types': [ 'error', { ignoreParameters: true }, ], + '@typescript-eslint/restrict-template-expressions': [ + 'error', + { + allowAny: false, + allowBoolean: false, + allowNever: false, + allowNullish: false, + allowNumber: true, + allowRegExp: false, + }, + ], // #endregion @typescript-eslint // #region import @@ -127,6 +136,7 @@ export default tseslint.config( 'no-shadow': 'error', 'no-undef': 'off', 'sort-imports': 'off', + // #endregion misc }, }, { diff --git a/packages/fs-router-vite-plugin/src/build-route-config.ts b/packages/fs-router-vite-plugin/src/build-route-config.ts index 11484d90..d4201719 100644 --- a/packages/fs-router-vite-plugin/src/build-route-config.ts +++ b/packages/fs-router-vite-plugin/src/build-route-config.ts @@ -3,7 +3,7 @@ import type { RouteNode } from './types' export function buildRouteConfig(nodes: Array, depth = 1): string { const children = nodes.map((node) => { - const route = `${node.variableName}Route` + const route = `${node.variableName as string}Route` if (node.children?.length) { const childConfigs = buildRouteConfig(node.children, depth + 1) diff --git a/packages/fs-router-vite-plugin/src/generator.ts b/packages/fs-router-vite-plugin/src/generator.ts index 20f640c7..f10e1101 100644 --- a/packages/fs-router-vite-plugin/src/generator.ts +++ b/packages/fs-router-vite-plugin/src/generator.ts @@ -157,14 +157,14 @@ export async function routeGenerator(config = defaultConfig): Promise { (d): number => (d.routePath.includes(`/${ROOT_PATH_ID}`) ? -1 : 1), (d): number => d.routePath.split('/').length, (d): number => (d.routePath.endsWith("index'") ? -1 : 1), - (d): any => d, + (d): RouteNode => d, ]) const imports = [ ...sortedRouteNodes.map((node) => { const extension = node.filePath.endsWith('mdx') ? '.mdx' : '' return `const ${ - node.variableName + node.variableName as string }Import = dynamic(() => import('./${replaceBackslash( removeExt( path.relative( @@ -181,18 +181,21 @@ export async function routeGenerator(config = defaultConfig): Promise { ...sortedRouteNodes.map((node) => { const isRoot = node.routePath.endsWith(ROOT_PATH_ID) const rootDeclaration = isRoot ? ', isRoot: true' : '' + const variableName = node.variableName as string - return `const ${node.variableName} = createRoute({ component: ${node.variableName}Import${rootDeclaration} })` + return `const ${variableName} = createRoute({ component: ${variableName}Import${rootDeclaration} })` }), ].join('\n') const createRouteUpdates = [ sortedRouteNodes .map((node) => { + const variableName = node.variableName as string + const cleanedPath = node.cleanedPath as string return [ - `const ${node.variableName}Route = ${node.variableName}.update({ + `const ${variableName}Route = ${variableName}.update({ ${[ - !node.path?.endsWith(ROOT_PATH_ID) && `path: '${node.cleanedPath}'`, + !node.path?.endsWith(ROOT_PATH_ID) && `path: '${cleanedPath}'`, `getParentRoute: () => ${node.parent?.variableName ?? 'root'}Route`, rustHandlersNodes.includes(node.path || '') ? 'hasHandler: true' @@ -236,7 +239,7 @@ export async function routeGenerator(config = defaultConfig): Promise { const routeTreeContent = await fsp .readFile(path.resolve(config.generatedRouteTree), 'utf-8') - .catch((e) => { + .catch((e: unknown) => { const err = e as Error & { code?: string } if (err.code === 'ENOENT') { return undefined diff --git a/packages/router/src/components/RouteMatch.spec.tsx b/packages/router/src/components/RouteMatch.spec.tsx index 09971be5..b7f3f9aa 100644 --- a/packages/router/src/components/RouteMatch.spec.tsx +++ b/packages/router/src/components/RouteMatch.spec.tsx @@ -42,7 +42,7 @@ describe('Test RouteMatch component', () => { test('It should correctly render nested routes', () => { vi.mock('../hooks/useServerSideProps.tsx', () => ({ - useServerSideProps: (): { data: any; isLoading: boolean } => { + useServerSideProps: (): { data: unknown; isLoading: boolean } => { return { data: undefined, isLoading: false, diff --git a/packages/router/src/dynamic.tsx b/packages/router/src/dynamic.tsx index 01d862cc..9ff7ac99 100644 --- a/packages/router/src/dynamic.tsx +++ b/packages/router/src/dynamic.tsx @@ -1,9 +1,9 @@ import * as React from 'react' -import type { ReactElement, ComponentType } from 'react' +import type { ReactElement } from 'react' import type { RouteComponent } from './types' -type ImportFn = () => Promise<{ default: React.ComponentType }> +type ImportFn = () => Promise<{ default: RouteComponent }> /** * Helper function to lazy load any component. @@ -44,7 +44,7 @@ export const dynamic = (importFn: ImportFn): React.JSX.Element => { export const __tuono__internal__lazyLoadComponent = ( factory: ImportFn, ): RouteComponent => { - let LoadedComponent: ComponentType | undefined + let LoadedComponent: RouteComponent | undefined const LazyComponent = React.lazy(factory) as unknown as RouteComponent const loadComponent = (): Promise => @@ -52,7 +52,9 @@ export const __tuono__internal__lazyLoadComponent = ( LoadedComponent = module.default }) - const Component = (props: any): ReactElement => + const Component = ( + props: React.ComponentProps, + ): ReactElement => React.createElement(LoadedComponent || LazyComponent, props) Component.preload = loadComponent diff --git a/packages/router/src/hooks/useRoute.spec.tsx b/packages/router/src/hooks/useRoute.spec.tsx index f3a5eae2..400a676a 100644 --- a/packages/router/src/hooks/useRoute.spec.tsx +++ b/packages/router/src/hooks/useRoute.spec.tsx @@ -8,7 +8,7 @@ describe('Test useRoute fn', () => { test('match routes by ids', () => { vi.mock('./useInternalRouter.tsx', () => ({ - useInternalRouter: (): { routesById: Record } => { + useInternalRouter: (): { routesById: Record } => { return { routesById: { '/': { id: '/' }, diff --git a/packages/router/src/hooks/useRouter.tsx b/packages/router/src/hooks/useRouter.tsx index 68a1fff2..35b85500 100644 --- a/packages/router/src/hooks/useRouter.tsx +++ b/packages/router/src/hooks/useRouter.tsx @@ -16,7 +16,7 @@ interface UseRouterHook { /** * This object contains all the query params of the current route */ - query: Record + query: Record /** * Returns the current pathname diff --git a/packages/router/src/hooks/useRouterStore.tsx b/packages/router/src/hooks/useRouterStore.tsx index e2e74d8c..7a5e4232 100644 --- a/packages/router/src/hooks/useRouterStore.tsx +++ b/packages/router/src/hooks/useRouterStore.tsx @@ -67,5 +67,7 @@ export const useRouterStore = create()((set) => ({ pendingMatches: [], cachedMatches: [], statusCode: 200, - updateLocation: (location: ParsedLocation): void => set({ location }), + updateLocation: (location: ParsedLocation): void => { + set({ location }) + }, })) diff --git a/packages/router/src/hooks/useServerSideProps.tsx b/packages/router/src/hooks/useServerSideProps.tsx index d6a8700f..09d984cc 100644 --- a/packages/router/src/hooks/useServerSideProps.tsx +++ b/packages/router/src/hooks/useServerSideProps.tsx @@ -13,7 +13,7 @@ interface UseServerSidePropsReturn { } interface TuonoApi { - data?: any + data?: unknown info: { redirect_destination?: string } diff --git a/packages/router/src/route.ts b/packages/router/src/route.ts index 2f5c8d1f..33bc7c28 100644 --- a/packages/router/src/route.ts +++ b/packages/router/src/route.ts @@ -77,7 +77,7 @@ export class Route { this.fullPath = fullPath || '' } - addChildren(routes: Array): Route { + addChildren(routes: Array): this { this.children = routes return this } diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index 3d3bb5fe..34653326 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -17,8 +17,6 @@ interface RouterOptions { routeTree?: RouteTree } -export type RouterType = any - export function createRouter(options: CreateRouterOptions): Router { return new Router(options) } diff --git a/packages/tuono/src/ssr/index.tsx b/packages/tuono/src/ssr/index.tsx index 644742f6..67e17123 100644 --- a/packages/tuono/src/ssr/index.tsx +++ b/packages/tuono/src/ssr/index.tsx @@ -84,7 +84,7 @@ export function serverSideRendering(routeTree: RouteTree) { ${renderToStaticMarkup(