Issue
I'm trying to extend the following Next.js function type:
export type GetStaticProps<
P extends { [key: string]: any } = { [key: string]: any },
Q extends ParsedUrlQuery = ParsedUrlQuery,
D extends PreviewData = PreviewData
> = (
context: GetStaticPropsContext<Q, D>
) => Promise<GetStaticPropsResult<P>> | GetStaticPropsResult<P>
So that 3 properties on its context (GetStaticPropsContext
) and never undefined
, like this:
type UpdateContext<T> = T extends (context: infer Context extends GetStaticPropsContext) => infer Return
? (context: SelectiveRequiredNotUndefined<Context, "locale" | "locales" | "defaultLocale">) => Return
: never;
Now if I do this, I can use the new type where those context properties are never undefined
:
type MyGetStaticProps = UpdateContext<GetStaticProps>;
const getStaticProps: MyGetStaticProps = async (context) => {
// do stuff
}
The problem is that MyGetStaticProps
is no longer generic. I know I could always do this instead:
type MyProps = {
someField: string
};
export const getStaticProps: UpdateContext<GetStaticProps<MyProps>> = async (context) => {
// do stuff
}
But I was wondering instead if there would not be a way to infer the type parameter definitions instead to avoid the more verbose syntax?
Just to recap, I am looking for a way to have some sort of type MyGetStaticProps = UpdateContext<GetStaticProps>;
but that would be supporting MyGetStaticProps<MyProps>
(infer the type parameters of GetStaticProps
)
Here is a fully working Playground link of the example
Solution
Unfortunately TypeScript cannot currently represent these kinds of types (known as "higher kinded types"), see microsoft/TypeScript#1213.
You could try and implement them, like this blog post does or this comment shows, but it's clunky and not fully representative of what HKTs can do.
It's probably better to use an alternative, or try to rethink your problem or even prevent it in the first place by redesigning some parts of your code.
In short, you can't really take a type, modify it, then spit the type back out, like you can with JS functions:
// type GetStaticProps<...> = ...;
function GetStaticProps(...) { ... }
// type UpdateContext<Func ...> = ...;
function UpdateContext(Func) {
const NewFunc = (...args) => {
args[0].prop = "something else";
return Func(...args);
};
return NewFunc;
}
// type Updated = UpdateContext<GetStaticProps>;
const Updated = UpdateContext(GetStaticProps);
// type Result = Updated<...>; // but Updated can't be a generic, it's a result of another type.
const Result = Updated({ prop: "will change" });
Some HKT comments from jcalz (more in-depth with potential workarounds for you):
Answered By - kelly
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.