The problem arises from the fact that you have not initialized the value for ['pickupPhoneNumber']
.
To address this issue, you can set it up in the following manner:
type PhoneFields = 'deliveryPhoneNumber' | 'pickupPhoneNumber'
type PhoneValues = {
[x in PhoneFields]: string
}
const f = (props: {
phoneField?: PhoneFields,
address: {
phone: string,
}
}) => {
const deliveryPhoneNumber = props.phoneField === 'deliveryPhoneNumber' ? props.address.phone : '';
const pickupPhoneNumber = props.phoneField === 'pickupPhoneNumber' ? props.address.phone : '';
const initialValues: PhoneValues = {
['deliveryPhoneNumber']: deliveryPhoneNumber,
['pickupPhoneNumber']: pickupPhoneNumber
}
}
Alternatively, you can modify your PhoneValues
as follows:
type PhoneValues = {
[x in PhoneFields]: string | undefined
}
Then, this will function correctly:
(props: {
phoneField?: PhoneFields,
address: {
phone: string,
}
}) => {
const initialValues = {
[props.phoneField ?? 'deliveryPhoneNumber']: props.address.phone ?? ''
}
}
UPDATE
If you prefer having either deliveryPhoneNumber
or pickupPhoneNumber
(but not both) in the type, you can implement it like this:
type PhoneFields = 'deliveryPhoneNumber' | 'pickupPhoneNumber';
type PhoneValues =
{ deliveryPhoneNumber: string, pickupPhoneNumber?: never }
| { deliveryPhoneNumber?: never, pickupPhoneNumber: string }
const f = (props: {
phoneField?: PhoneFields,
address: {
phone?: string,
}
}): PhoneValues => {
const result: PhoneValues = {
[props.phoneField ?? 'deliveryPhoneNumber']: props.address.phone ?? ''
} as unknown as PhoneValues;
console.log(result);
return result;
}
f({phoneField: 'deliveryPhoneNumber', address: {phone: '123'}});
f({phoneField: 'pickupPhoneNumber', address: {phone: '456'}});
f({address: {phone: '789'}});
f({address: {}});
In the code above, a double assertion is used due to Typescript's inability to infer { [key: string]: string }
as equivalent to PhoneValues
, even when key
is of type PhoneFields
.
If you wish to avoid the double assertion, you could structure it as shown below:
type PhoneFields = 'deliveryPhoneNumber' | 'pickupPhoneNumber';
type PhoneValues =
{ deliveryPhoneNumber: string, pickupPhoneNumber?: never }
| { deliveryPhoneNumber?: never, pickupPhoneNumber: string }
const f = (props: {
phoneField?: PhoneFields,
address: {
phone?: string,
}
}): PhoneValues => {
let result: PhoneValues;
switch (props.phoneField) {
case 'pickupPhoneNumber':
result = {
pickupPhoneNumber: props.address.phone ?? ''
};
break;
default:
result = {
deliveryPhoneNumber: props.address.phone ?? ''
};
break;
}
console.log(result);
return result;
}
f({ phoneField: 'deliveryPhoneNumber', address: { phone: '123'}});
f({ phoneField: 'pickupPhoneNumber', address: { phone: '456'}});
f({ address: { phone: '789'}});
f({ address: {}});