[英]Next.js GetServerSideProps custom wrapper TypeScript
我为GetServerSideProps
SSR 函数创建了一个包装器以减少重复,但我在使用 TypeScript 正确键入它时遇到了问题。 这是包装:
type WithSessionType = <T extends {}>(
callback: GetServerSideProps<T>
) => GetServerSideProps<{ session: Session | null } & T>
// v error
const withSession: WithSessionType = (callback) => async (ctx) => {
const session = await getSession(ctx)
const result = await callback?.(ctx)
const props = result && 'props' in result ? result.props : {}
return {
...result,
props: {
session,
...props,
},
}
}
错误:
Type '(ctx: GetServerSidePropsContext<ParsedUrlQuery, PreviewData>) => Promise<{ props: { session: Session | null; }; redirect: Redirect; } | { ...; } | { ...; }>' is not assignable to type 'GetServerSideProps<{ session: Session | null; } & T, ParsedUrlQuery, PreviewData>'.
Type 'Promise<{ props: { session: Session | null; }; redirect: Redirect; } | { props: { session: Session | null; }; notFound: true; } | { props: { session: Session | null; }; }>' is not assignable to type 'Promise<GetServerSidePropsResult<{ session: Session | null; } & T>>'.
Type '{ props: { session: Session | null; }; redirect: Redirect; } | { props: { session: Session | null; }; notFound: true; } | { props: { session: Session | null; }; }' is not assignable to type 'GetServerSidePropsResult<{ session: Session | null; } & T>'.
Type '{ props: { session: Session | null; }; }' is not assignable to type 'GetServerSidePropsResult<{ session: Session | null; } & T>'.
Type '{ props: { session: Session | null; }; }' is not assignable to type '{ props: ({ session: Session | null; } & T) | Promise<{ session: Session | null; } & T>; }'.
Types of property 'props' are incompatible.
Type '{ session: Session | null; }' is not assignable to type '({ session: Session | null; } & T) | Promise<{ session: Session | null; } & T>'.
Type '{ session: Session | null; }' is not assignable to type '{ session: Session | null; } & T'.
Type '{ session: Session | null; }' is not assignable to type 'T'.
'{ session: Session | null; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.ts(2322)
用例(有效):
export const getServerSideProps = withSession(async () => {
return {
props: {
custom: 'custom string type',
},
}
})
这是getServerSideProps
的计算类型:
const getServerSideProps: GetServerSideProps<{
session: Session | null;
} & {
custom: string;
}, ParsedUrlQuery, PreviewData>
它工作正常,甚至InferGetServerSidePropsType
也能正确推断类型,但仍然会出现上述错误。
知道如何让 TypeScript 在这里开心吗? 如果您有任何关于这种包装器的建议和技巧,也期待着。
我找到了原因,但我不太明白为什么会这样。结果它认为这个陈述总是错误的,即使props
可以存在于这种类型上。
GetServerSidePropsResult 类型:
export type GetServerSidePropsResult<P> =
| { props: P | Promise<P> }
| { redirect: Redirect }
| { notFound: true }
为什么只有redirect
在这种类型上可见,而不是props
或notFound
?
不太确定,但我认为问题在于 T 可能有另一个会话定义,因此该类型不再可分配。 您可以只使用Omit<T,"session">
从 T 中排除会话,或者您可以编写类似<T extends { session?: Session | null >
<T extends { session?: Session | null >
而不是<T extends {}>
顺便提一句。 {}
在实践中的 TS 意味着“任何非空值”,因此您应该考虑使用类似Record<string| number, any>
Record<string| number, any>
代替
(未测试,写在我的手机上,所以可能有错误)
该问题在另一个问题中进行了描述: 如何修复 TS2322:“可以使用不同的约束‘对象’子类型来实例化”?
我无法理解应该做什么才能让 TS 开心,但我有一个解决方法是强制转换返回的函数而不是声明返回的类型:
function withSession<T extends {}>(callback: GetServerSideProps<T>){
return (async (ctx) => {
const session = await getSession(ctx)
const result = await callback?.(ctx)
const props = result && 'props' in result ? result.props : {}
return {
...result,
props: {
session,
...props,
},
}
}) as GetServerSideProps<{ session: Session | null } & T>
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.