I'm facing a challenge with two interfaces that represent the data returned by an API and the actual data itself.
interface APIModelCommon {
id: number
createdAt: string
updatedAt: string
}
interface ModelCommon {
id: number
createdAt: Date
updatedAt: Date
}
I've been struggling to write a function that properly converts the API model to the correct type. Previously, I had to resort to type assertions with eslint-disable
comments, but I want to handle this issue more effectively.
The goal is to convert
interface APIArchive extends APIModelCommon
to interface Archive extends ModelCommon
, for instance.
Every attempt I've made so far has resulted in errors, and I haven't been able to find a solution.
function correctScrapedModel<A extends APIModelCommon, T extends ModelCommon>(apiModel: A): T {
const clone: T = (({ createdAt: _, updatedAt: __, ...o }) => ({
...o,
createdAt: new Date(),
updatedAt: new Date(),
}))(apiModel)
clone.createdAt = new Date(apiModel.createdAt)
clone.updatedAt = new Date(apiModel.updatedAt)
return clone
}
Currently, the function is generating this error:
TS2322: Type 'Omit<A, "createdAt" | "updatedAt"> & { createdAt: Date; updatedAt: Date; }' is not assignable to type 'T'. 'Omit<A, "createdAt" | "updatedAt"> & { createdAt: Date; updatedAt: Date; }' can be assigned to the constraint of type 'T', but 'T' might use a different subtype of constraint 'ModelCommon'.
The temporary fix involves using:
function correctScrapedModel<A extends APIModelCommon, T extends ModelCommon>(apiModel: A): T {
const clone = (({ createdAt: _, updatedAt: __, ...o }) => ({
...o,
createdAt: new Date(),
updatedAt: new Date(),
} as unknown as T))(apiModel)
clone.createdAt = new Date(apiModel.createdAt)
clone.updatedAt = new Date(apiModel.updatedAt)
return clone
}
However, I prefer avoiding as unknown as TYPE
statements if possible.
Is there a better approach to resolve this? If there's a way to inform Typescript that
Omit<APIModelCommon, 'createdAt' | 'updatedAt'> & { createdAt: Date, updatedAt: Date}
is equal to ModelCommon
, that would likely solve the issue, but I am unaware of how to do that.