I am facing a scenario where I have two distinct interfaces: A
and B
, both sharing a common property. Additionally, I possess two arrays containing items typed with either one of these interfaces. My objective is to create a function that can map these arrays to modify the shared property, while ensuring that the return type matches the type of the argument (A[]
or B[]
).
To illustrate this challenge, you can view an example in the TS playground link:
interface A {
requiredField: string;
optionalField: string;
}
interface B {
requiredField: string;
}
export const addOptionalData = (
list: A[] | B[]
) =>
list.map(listItem => {
listItem.requiredField = 'new value'
return listItem;
})
const list: A[] = [{
requiredField: 'original value',
optionalField: 'original value'
}]
let enrichedListA: A[] = addOptionalData(list) // The TS-error occurs at this point
let enrichedListB: B[] = addOptionalData(list)
However, TypeScript throws an error for the enrichedListA
variable, stating:
Type '(A | B)[]' is not assignable to type 'A[]'. Type 'A | B' is not assignable to type 'A'. Property 'optionalField' is missing in type 'B', which is required in type 'A'.
In my attempt to address this issue using Generics and conditional types, I encountered new errors in the updated approach as seen in this TS playground link:
interface A {
requiredField: string;
optionalField: string;
}
interface B {
requiredField: string;
}
type ObjectType<T> =
T extends A ? A :
T extends B ? B :
never;
export const addOptionalData = <T extends A | B>(
list: T
): ObjectType<T> =>
list.map(listItem => { // An error arises here stating: "Property 'map' does not exist on type 'A | B'"
listItem.requiredField = 'new value'
return listItem;
})
const list: A[] = [{
requiredField: 'original value',
optionalField: 'original value'
}]
let enrichedListA: A[] = addOptionalData(list) // Errors persist here
let enrichedListB: B[] = addOptionalData(list) // And also here