【发布时间】:2022-11-10 19:26:06
【问题描述】:
我正在尝试重构以下代码,以便我可以以类型安全的方式在多个页面上重用相同的中间件逻辑。但是,我很难编写适用于以下用例的类型安全递归类型。
工作原始代码:
import { NextPage, GetServerSidePropsContext } from 'next';
// new InferGetServerSidePropsType fix, waiting for merge to stable
type InferGetServerSidePropsType<T extends (args: any) => any> = Awaited<
Extract<Awaited<ReturnType<T>>, { props: any }>['props']
>;
const getServerSideProps = async (context: GetServerSidePropsContext) =>
(async (context, props) => {
const token = 'token';
if (Math.random() > 0.5)
return {
notFound: true,
};
return (async (context, props) => {
if (context.locale === 'en')
return {
redirect: {
destination: '/en',
permanent: true,
},
};
const permissions = [1, 2, 3];
return (async (context, props) => {
const data = 'data';
return { props: { ...props, data } };
})(context, { ...props, permissions });
})(context, { ...props, token });
})(context, {});
const MyPage: NextPage<InferGetServerSidePropsType<typeof getServerSideProps>> = (props) => {
const { token, permissions, data } = props; // types are infered correctly!
return null;
};
在我第一次尝试键入中间件之间的递归交集时,我得到了这个损坏的代码:
const withToken: GSSPMiddleware<{ token: string }> = (next) => async (context, props) => {
if (Math.random() > 0.5)
return {
notFound: true,
};
const token = 'token';
return next(context, { ...props, token });
};
const withPermissions: GSSPMiddleware<{ permissions: number[]}> = (next) => async (context, props) => {
if (context.locale === 'en')
return {
redirect: {
destination: '/en',
permanent: true,
},
};
const permissions = [1, 2, 3];
return next(context, { ...props, permissions });
};
const getServerSideProps = async (context: GetServerSidePropsContext) =>
withToken(
withPermissions(async (context, props) => { // props: {token: string} & {permissions: number[]}
const data = "data";
return { props: { ...props, data } };
})
)(context, {});
const MyPage: NextPage<InferGetServerSidePropsType<typeof getServerSideProps>> = (props) => {
const { token, permissions, data } = props; // types should infer correctly!
return null;
};
// My attempt, completely wrong
type GSSPMiddleware<Params extends { [key: string]: any } | undefined = undefined> = <
P extends { [key: string]: any } = { [key: string]: any },
>(
next: (
context: GetServerSidePropsContext,
props: Params extends undefined ? P : P & Params
) => Promise<GetServerSidePropsResult<Params extends undefined ? P : P & Params>>
) => (
context: GetServerSidePropsContext,
props: P
) => Promise<GetServerSidePropsResult<Params extends undefined ? P : P & Params>>;
我应该如何重构这段代码并编写这种类型?
【问题讨论】:
-
缺少
ParseUrlQuery的定义。 -
this 你的问题是什么?由于所有额外的 Next.js 特定的 BS,很难说出发生了什么。它会大大如果您可以将问题简化为不需要 Next.js 特定内容的示例,则可以提供帮助。就像在我的示例中一样,我尝试在不需要 Next.js 的情况下复制您的问题。它是公正的还是我错过了什么?
-
我在这里有一个类型安全的多中间件解决方案 stackblitz.com/edit/nextjs-eqqhbs?file=pages%2Fapi%2Fhello.ts 。不确定您是否可以使用 1:1 但这是一个好的开始
标签: typescript next.js