From abe4f38a5eec25499ec67a032bd2d1b2e7214a93 Mon Sep 17 00:00:00 2001 From: Alex Johansson Date: Mon, 4 Oct 2021 11:48:40 +0200 Subject: [PATCH] `` type inference improvement (#849) * asserts that `query.data` is never `null` when using `` --- lib/{hooks => }/QueryCell.tsx | 31 +++++++++++++++++++++++++------ pages/bookings/[status].tsx | 2 +- 2 files changed, 26 insertions(+), 7 deletions(-) rename lib/{hooks => }/QueryCell.tsx (54%) diff --git a/lib/hooks/QueryCell.tsx b/lib/QueryCell.tsx similarity index 54% rename from lib/hooks/QueryCell.tsx rename to lib/QueryCell.tsx index 9ed48341..968121ca 100644 --- a/lib/hooks/QueryCell.tsx +++ b/lib/QueryCell.tsx @@ -13,28 +13,47 @@ import { Alert } from "@components/ui/Alert"; type ErrorLike = { message: string; }; -interface QueryCellOptions { + +interface QueryCellOptionsBase { query: UseQueryResult; - success: (query: QueryObserverSuccessResult) => JSX.Element; error?: ( query: QueryObserverLoadingErrorResult | QueryObserverRefetchErrorResult ) => JSX.Element; loading?: (query: QueryObserverLoadingResult) => JSX.Element; idle?: (query: QueryObserverIdleResult) => JSX.Element; +} + +interface QueryCellOptionsNoEmpty + extends QueryCellOptionsBase { + success: (query: QueryObserverSuccessResult) => JSX.Element; +} + +interface QueryCellOptionsWithEmpty + extends QueryCellOptionsBase { + success: (query: QueryObserverSuccessResult, TError>) => JSX.Element; /** * If there's no data (`null`, `undefined`, or `[]`), render this component */ - empty?: (query: QueryObserverSuccessResult) => JSX.Element; + empty: (query: QueryObserverSuccessResult) => JSX.Element; } -export function QueryCell(opts: QueryCellOptions) { +export function QueryCell( + opts: QueryCellOptionsWithEmpty +): JSX.Element; +export function QueryCell( + opts: QueryCellOptionsNoEmpty +): JSX.Element; +export function QueryCell( + opts: QueryCellOptionsNoEmpty | QueryCellOptionsWithEmpty +) { const { query } = opts; if (query.status === "success") { - if (opts.empty && (query.data == null || (Array.isArray(query.data) && query.data.length === 0))) { + if ("empty" in opts && (query.data == null || (Array.isArray(query.data) && query.data.length === 0))) { return opts.empty(query); } - return opts.success(query); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return opts.success(query as any); } if (query.status === "error") { return ( diff --git a/pages/bookings/[status].tsx b/pages/bookings/[status].tsx index cae178ca..b1b72b9e 100644 --- a/pages/bookings/[status].tsx +++ b/pages/bookings/[status].tsx @@ -1,7 +1,7 @@ import { CalendarIcon } from "@heroicons/react/outline"; import { useRouter } from "next/router"; -import { QueryCell } from "@lib/hooks/QueryCell"; +import { QueryCell } from "@lib/QueryCell"; import { inferQueryInput, trpc } from "@lib/trpc"; import BookingsShell from "@components/BookingsShell";