I have a component for making HTTP requests, and one of the properties ('address'
) should be optional, since I don't need it in one of the components where I call that function.
The way I did it before is to use the Partial utility type, but I want to be more specific and make a use of Pick.
Old version:
export type Trip = {
address: string
product: string
no: number
customer: string
delievered: boolean
name: string
surname: string
}
export const usePostTrip = () => {
const queryClient = useQueryClient()
const mutation = useMutation(
async (data: Partial<Trip>) => { // This is achieved with Partial
const url = `${BASE_URL}/trip`
return axios.post(url, data ).catch((e) => console.log(e.message))
},
)
return mutation
}
Here is my current solution, which I believe is not the best one. Is there a better solution for this case?
export type Trip = {
address: string
product: string
no: number
customer: string
}
type tripWithoutAddress = Pick<
Trip, 'product'| 'no'
>
type tripsWithAddress = Pick<
Trip, 'product'| 'no' | 'address'
>
export const usePostTrip = () => {
const queryClient = useQueryClient()
const mutation = useMutation(
async (data: tripWithoutAddress | tripsWithAddress) => { // This is achieved with Pick
const url = `${BASE_URL}/trip`
return axios.post(url, data).catch((e) => console.log(e.message))
},
)
return mutation
}
I think Jimmy's answer is good, but:
If you ever change the address
property on Trip
(e.g. from string
to number
), you'll also have to manually change the optional version in order to maintain type consistency.
By using Pick
and Partial
, you can parametrically derive the type from Trip
: any changes to the address
property on Trip
will automatically be changed in the derived type, too:
type Trip = {
address: string;
customer: string;
no: number;
product: string;
}
type TripWithOptionalAddress = Omit<Trip, 'address'> & Partial<Pick<Trip, 'address'>>;
declare const t: TripWithOptionalAddress;
t.address // string | undefined