Named parameters and the `Partial` type


While doing some work around default URL parameters we found ourselves wanting a way to implement a function that acted similarly to a python function with named parameters. We wanted to be able to pass in one or all of the parameters and if we did not provide the parameter, we wanted a default value to be used. We also wanted our implementation to be consistent within the type-system. We settled on the following implementation:
type UrlParams = {
page: number;
sort: "asc" | "desc";
search: string;
};
type OptionalUrlParams = {
page?: number;
sort?: "asc" | "desc";
search?: string;
};
const sanitizedParams = getSanitizedParams();
const updateUrlParameters = ({
page = sanitizedParams.page,
sort = sanitizedParams.sort,
search = sanitizedParams.search,
}: OptionalUrlParams) => dispatch(push(`list/${page}/${sort}/${search}`));
In order to allow the consumer of updateUrlParameters
to pass in one or all of
the parameters, we manually created a version of UrlParams
that made every
property optional.
We could use this with a call like updateUrlParameters({ page: 1 })
. The OptionalUrlParams
type declaration bothered me for sure, but it seemed like the best approach given the constraints.
Partial
to the rescue
Not even 24 hours later, while browsing the TypeScript docs (that’s a normal thing to do — thank you), I
noticed the Partial
utility type.
Constructs a type with all properties of T set to optional. This utility will return a type that represents all subsets of a given type.
I hadn’t been looking for a way to clean up the implementation but it seemed
ungrateful to the powers that be not to give it a try. After tossing that OptionalUrlParams
type aside and dropping in
Partial
we had something that looked healthier and functioned the same.
type UrlParams = {
page: number;
sort: "asc" | "desc";
search: string;
};
const sanitizedParams = getSanitizedParams();
const updateUrlParameters = ({
page = sanitizedParams.page,
sort = sanitizedParams.sort,
search = sanitizedParams.search,
}: Partial<UrlParams>) => dispatch(push(`list/${page}/${sort}/${search}`));
Now, if we needed to alter the URL parameters in any way we wouldn’t have to ensure we also updated the optional version. I haven’t been working in TypeScript long but I’ve learned that unless you lock things down,
Happily ever after
Finding Partial
was a bit of a relief on a few levels:
- I’m not the only one who’s ever wanted to make every property of a type optional
- There’s a way to do it without having to create a new type declaration