From d562aa87a378286668ae65247dd1d47353d5daed Mon Sep 17 00:00:00 2001 From: Marco Pasqualetti <24919330+marcalexiei@users.noreply.github.com> Date: Tue, 18 Mar 2025 09:07:38 +0100 Subject: [PATCH] feat(packages/tuono): improve `TuonoRouteProps` type (#648) --- e2e/fixtures/base/src/routes/index.tsx | 8 ++--- examples/tuono-app/src/routes/index.tsx | 4 +-- examples/tuono-tutorial/src/routes/index.tsx | 4 +-- .../src/routes/pokemons/[pokemon].tsx | 4 +-- packages/tuono/src/index.ts | 2 +- packages/tuono/src/types.spec-d.ts | 33 +++++++++++++++++++ packages/tuono/src/types.ts | 13 +++++--- packages/tuono/vite.config.ts | 6 ++++ 8 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 packages/tuono/src/types.spec-d.ts diff --git a/e2e/fixtures/base/src/routes/index.tsx b/e2e/fixtures/base/src/routes/index.tsx index 87f3f8fe..8f809d57 100644 --- a/e2e/fixtures/base/src/routes/index.tsx +++ b/e2e/fixtures/base/src/routes/index.tsx @@ -1,5 +1,5 @@ import type { JSX } from 'react' -import type { TuonoProps } from 'tuono' +import type { TuonoRouteProps } from 'tuono' import { Link } from 'tuono' interface IndexProps { @@ -9,7 +9,7 @@ interface IndexProps { export default function IndexPage({ data, isLoading, -}: TuonoProps): JSX.Element { +}: TuonoRouteProps): JSX.Element { if (isLoading) { return

Loading...

} @@ -17,8 +17,8 @@ export default function IndexPage({ return ( <>

TUONO

-

{data?.subtitle}

- Routing link) +

{data.subtitle}

+ Routing link ) } diff --git a/examples/tuono-app/src/routes/index.tsx b/examples/tuono-app/src/routes/index.tsx index 13d1439b..b6558706 100644 --- a/examples/tuono-app/src/routes/index.tsx +++ b/examples/tuono-app/src/routes/index.tsx @@ -1,5 +1,5 @@ import type { JSX } from 'react' -import type { TuonoProps } from 'tuono' +import type { TuonoRouteProps } from 'tuono' interface IndexProps { subtitle: string @@ -8,7 +8,7 @@ interface IndexProps { export default function IndexPage({ data, isLoading, -}: TuonoProps): JSX.Element { +}: TuonoRouteProps): JSX.Element { if (isLoading) { return

Loading...

} diff --git a/examples/tuono-tutorial/src/routes/index.tsx b/examples/tuono-tutorial/src/routes/index.tsx index 54dc1172..7cc23c44 100644 --- a/examples/tuono-tutorial/src/routes/index.tsx +++ b/examples/tuono-tutorial/src/routes/index.tsx @@ -1,6 +1,6 @@ // src/routes/index.tsx import type { JSX } from 'react' -import type { TuonoProps } from 'tuono' +import type { TuonoRouteProps } from 'tuono' import PokemonLink from '../components/PokemonLink' @@ -10,7 +10,7 @@ interface IndexProps { export default function IndexPage({ data, -}: TuonoProps): JSX.Element | null { +}: TuonoRouteProps): JSX.Element | null { if (!data?.results) return null return ( diff --git a/examples/tuono-tutorial/src/routes/pokemons/[pokemon].tsx b/examples/tuono-tutorial/src/routes/pokemons/[pokemon].tsx index 715fe2c8..43f384e2 100644 --- a/examples/tuono-tutorial/src/routes/pokemons/[pokemon].tsx +++ b/examples/tuono-tutorial/src/routes/pokemons/[pokemon].tsx @@ -1,6 +1,6 @@ // src/routes/pokemons/[pokemon].tsx import type { JSX } from 'react' -import type { TuonoProps } from 'tuono' +import type { TuonoRouteProps } from 'tuono' import { Link } from 'tuono' import PokemonView from '../../components/PokemonView' @@ -15,7 +15,7 @@ interface Pokemon { export default function PokemonPage({ isLoading, data, -}: TuonoProps): JSX.Element { +}: TuonoRouteProps): JSX.Element { return (
Back diff --git a/packages/tuono/src/index.ts b/packages/tuono/src/index.ts index 905c6a47..ca9022b8 100644 --- a/packages/tuono/src/index.ts +++ b/packages/tuono/src/index.ts @@ -13,4 +13,4 @@ export { export { TuonoScripts } from './shared/TuonoScripts' -export type { TuonoProps } from './types' +export type { TuonoRouteProps } from './types' diff --git a/packages/tuono/src/types.spec-d.ts b/packages/tuono/src/types.spec-d.ts new file mode 100644 index 00000000..a2001be0 --- /dev/null +++ b/packages/tuono/src/types.spec-d.ts @@ -0,0 +1,33 @@ +import { describe, it, expectTypeOf } from 'vitest' + +import type { TuonoRouteProps } from './types' + +describe('TuonoRouteProps', () => { + interface MyData { + something: string + } + + type RouteProps = TuonoRouteProps + + it('should have correct union types', () => { + expectTypeOf() + .toHaveProperty('isLoading') + .toEqualTypeOf() + + expectTypeOf() + .toHaveProperty('data') + .toEqualTypeOf() + }) + + it('should correctly infer `data` based upon `isLoading`', () => { + expectTypeOf() + .extract<{ isLoading: true }>() + .toHaveProperty('data') + .toEqualTypeOf() + + expectTypeOf() + .extract<{ isLoading: false }>() + .toHaveProperty('data') + .toEqualTypeOf() + }) +}) diff --git a/packages/tuono/src/types.ts b/packages/tuono/src/types.ts index 5c2fcb45..6177d14b 100644 --- a/packages/tuono/src/types.ts +++ b/packages/tuono/src/types.ts @@ -47,7 +47,12 @@ export interface ServerPayload { ) */ -export interface TuonoProps { - data?: T - isLoading: boolean -} +export type TuonoRouteProps = + | { + data: null + isLoading: true + } + | { + data: TData + isLoading: false + } diff --git a/packages/tuono/vite.config.ts b/packages/tuono/vite.config.ts index 2a3839d4..909bcefc 100644 --- a/packages/tuono/vite.config.ts +++ b/packages/tuono/vite.config.ts @@ -12,6 +12,12 @@ export default mergeConfig( */ build: { target: 'es2022' }, plugins: [react()], + + test: { + typecheck: { + enabled: true, + }, + }, }), defineViteConfig({ entry: [