I have this type:
type Period = 'Monthly' | 'Yearly'
type Cycle = {
period: Period,
price: number
}
And I want to get the following type (basically, allow period to be an empty string):
type Period = 'Monthly' | 'Yearly'
type EditableCycle = {
period: Period | '',
price: number
}
I was thinking about something like this made up syntax:
type EditableCycle = Extend<Cycle, { period: '' }>
How can I achieve it?
The reason, I want the user to be able to don't choose any period when editing (hende period can be an empty string) but after validating it I'm sure period will hold a valid Period.
note: the real type is much more complicated than Cycle, involving arrays and similar stuff, this is a cut down example.
CodePudding user response:
You can use the Omit
utility type to override the period
field:
type Period = 'Monthly' | 'Yearly'
type Cycle = {
period: Period,
price: number
}
type EditableCycle = Omit<Cycle, "period"> & {
period: Period | ''
}
const editableCycle: EditableCycle = {
period: '',
price: 5
}
If this solution works for you, you can go one step further and create your own Override
type like this:
type Period = 'Monthly' | 'Yearly'
type Cycle = {
period: Period,
price: number
}
type Override<T, K> = Omit<T, keyof K> & K
type EditableCycle = Override<Cycle, {
period: Period | ''
}>
const editableCycle: EditableCycle = {
period: '',
price: 5
}
I hope you find this answer helpful.
François
CodePudding user response:
Here's how to type the Extend
utility in your question (I've renamed it to UnifyProps
because it produces a new type including all properties in both parameters, creating a union of the types of parameters with shared names):
type UnifyProps<T1, T2> = {
[K in keyof T1]: K extends keyof T2 ? (T1[K] | T2[K]) : T1[K];
} & {
[K in keyof T2]: K extends keyof T1 ? (T1[K] | T2[K]) : T2[K];
};
type Period = 'Monthly' | 'Yearly';
type Cycle = {
period: Period;
price: number;
};
type EditableCycle = UnifyProps<Cycle, { period: '' }>;
declare const ec: EditableCycle;
ec.period = 'Monthly'; // ok
ec.period = 'Yearly'; // ok
ec.period = ''; // ok
ec.period = 'another string'; /*
^^^^^^^^^
Type '"another string"' is not assignable to type '"" | Period'. (2322) */