summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/shiny-dryers-swim.md5
-rw-r--r--packages/astro/client.d.ts2
-rw-r--r--packages/astro/src/@types/astro.ts42
-rw-r--r--packages/astro/src/core/render/paginate.ts12
-rw-r--r--packages/astro/src/core/render/route-cache.ts5
5 files changed, 53 insertions, 13 deletions
diff --git a/.changeset/shiny-dryers-swim.md b/.changeset/shiny-dryers-swim.md
new file mode 100644
index 000000000..f943b2180
--- /dev/null
+++ b/.changeset/shiny-dryers-swim.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Paginate will now return exact types instead of a naive Record
diff --git a/packages/astro/client.d.ts b/packages/astro/client.d.ts
index e6389d415..9d064c0b1 100644
--- a/packages/astro/client.d.ts
+++ b/packages/astro/client.d.ts
@@ -57,7 +57,7 @@ declare module 'astro:assets' {
};
type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
- type Simplify<T> = { [KeyType in keyof T]: T[KeyType] };
+ type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};
type ImgAttributes = WithRequired<
Omit<import('./types').HTMLAttributes<'img'>, 'src' | 'width' | 'height'>,
'alt'
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index bc47e0779..3efbb7ae8 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -1600,7 +1600,9 @@ export type GetStaticPaths = (
* const { slug } = Astro.params as Params;
* ```
*/
-export type InferGetStaticParamsType<T> = T extends () => infer R | Promise<infer R>
+export type InferGetStaticParamsType<T> = T extends (
+ opts?: GetStaticPathsOptions
+) => infer R | Promise<infer R>
? R extends Array<infer U>
? U extends { params: infer P }
? P
@@ -1631,7 +1633,9 @@ export type InferGetStaticParamsType<T> = T extends () => infer R | Promise<infe
* const { propA, propB } = Astro.props;
* ```
*/
-export type InferGetStaticPropsType<T> = T extends () => infer R | Promise<infer R>
+export type InferGetStaticPropsType<T> = T extends (
+ opts: GetStaticPathsOptions
+) => infer R | Promise<infer R>
? R extends Array<infer U>
? U extends { props: infer P }
? P
@@ -1678,13 +1682,13 @@ export type MarkdownContent<T extends Record<string, any> = Record<string, any>>
*
* [Astro reference](https://docs.astro.build/en/reference/api-reference/#paginate)
*/
-export interface PaginateOptions {
+export interface PaginateOptions<PaginateProps extends Props, PaginateParams extends Params> {
/** the number of items per-page (default: `10`) */
pageSize?: number;
/** key: value object of page params (ex: `{ tag: 'javascript' }`) */
- params?: Params;
+ params?: PaginateParams;
/** object of props to forward to `page` result */
- props?: Props;
+ props?: PaginateProps;
}
/**
@@ -1718,7 +1722,33 @@ export interface Page<T = any> {
};
}
-export type PaginateFunction = (data: any[], args?: PaginateOptions) => GetStaticPathsResult;
+type OmitIndexSignature<ObjectType> = {
+ // eslint-disable-next-line @typescript-eslint/ban-types
+ [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown>
+ ? never
+ : KeyType]: ObjectType[KeyType];
+};
+// eslint-disable-next-line @typescript-eslint/ban-types
+type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};
+export type PaginateFunction = <
+ PaginateData,
+ AdditionalPaginateProps extends Props,
+ AdditionalPaginateParams extends Params,
+>(
+ data: PaginateData[],
+ args?: PaginateOptions<AdditionalPaginateProps, AdditionalPaginateParams>
+) => {
+ params: Simplify<
+ {
+ page: string | undefined;
+ } & OmitIndexSignature<AdditionalPaginateParams>
+ >;
+ props: Simplify<
+ {
+ page: Page<PaginateData>;
+ } & OmitIndexSignature<AdditionalPaginateProps>
+ >;
+}[];
export type Params = Record<string, string | undefined>;
diff --git a/packages/astro/src/core/render/paginate.ts b/packages/astro/src/core/render/paginate.ts
index dffabe178..f8cd8709d 100644
--- a/packages/astro/src/core/render/paginate.ts
+++ b/packages/astro/src/core/render/paginate.ts
@@ -1,18 +1,20 @@
import type {
- GetStaticPathsResult,
Page,
PaginateFunction,
+ PaginateOptions,
Params,
Props,
RouteData,
} from '../../@types/astro';
import { AstroError, AstroErrorData } from '../errors/index.js';
-export function generatePaginateFunction(routeMatch: RouteData): PaginateFunction {
+export function generatePaginateFunction(
+ routeMatch: RouteData
+): (...args: Parameters<PaginateFunction>) => ReturnType<PaginateFunction> {
return function paginateUtility(
data: any[],
- args: { pageSize?: number; params?: Params; props?: Props } = {}
- ) {
+ args: PaginateOptions<Props, Params> = {}
+ ): ReturnType<PaginateFunction> {
let { pageSize: _pageSize, params: _params, props: _props } = args;
const pageSize = _pageSize || 10;
const paramName = 'page';
@@ -31,7 +33,7 @@ export function generatePaginateFunction(routeMatch: RouteData): PaginateFunctio
}
const lastPage = Math.max(1, Math.ceil(data.length / pageSize));
- const result: GetStaticPathsResult = [...Array(lastPage).keys()].map((num) => {
+ const result = [...Array(lastPage).keys()].map((num) => {
const pageNum = num + 1;
const start = pageSize === Infinity ? 0 : (pageNum - 1) * pageSize; // currentPage is 1-indexed
const end = Math.min(start + pageSize, data.length);
diff --git a/packages/astro/src/core/render/route-cache.ts b/packages/astro/src/core/render/route-cache.ts
index f607cf5d9..d43ce514b 100644
--- a/packages/astro/src/core/render/route-cache.ts
+++ b/packages/astro/src/core/render/route-cache.ts
@@ -3,6 +3,7 @@ import type {
GetStaticPathsItem,
GetStaticPathsResult,
GetStaticPathsResultKeyed,
+ PaginateFunction,
Params,
RouteData,
RuntimeMode,
@@ -50,7 +51,9 @@ export async function callGetStaticPaths({
// Calculate your static paths.
let staticPaths: GetStaticPathsResult = [];
staticPaths = await mod.getStaticPaths({
- paginate: generatePaginateFunction(route),
+ // Q: Why the cast?
+ // A: So users downstream can have nicer typings, we have to make some sacrifice in our internal typings, which necessitate a cast here
+ paginate: generatePaginateFunction(route) as PaginateFunction,
rss() {
throw new AstroError(AstroErrorData.GetStaticPathsRemovedRSSHelper);
},