type FromType = {
// [...]
value: string;
}
type ToType = Omit<FromType, 'value'> & {
value: number;
}
then
/**
* @param {FromType[]} records
* @returns {ToType[]} records
*/
function transform(records){
return records.map((record) => {
record.value = parseFloat(record.value);
return record;
});
}
Complains because record.value
is expected to be a string. A workaround is to use Object.assign
/**
* @param {FromType[]} records
* @returns {ToType[]} records
*/
function transform(records){
return records.map((record) => {
return Object.assign(record, {
value: parseFloat(record.value),
});
});
}
How can I handle type casting on assignment?
Assume:
string | number
.{ ...item, value: 0 }
;With apologies, I don't know how to annotation this with JSDoc, but with TypeScript's own type annotations in order to perform that mutation you'd briefly lie to TypeScript to trick it into allowing it:
type FromType = {
// [...]
value: string;
};
type ToType = Omit<FromType, "value"> & {
value: number;
};
type X = ToType["value"];
/**
* @param records The record to transform.
* @returns Transformed records.
*/
function transform(records: FromType[]): ToType[] {
return records.map((record) => {
const result = record as any as ToType; // A brief lie...
result.value = parseFloat(record.value); // ...which is now true
return result;
});
}
Live example on the playground
If you could avoid mutation, I would strongly encourage it (it would then just be return records.map((value, ...rest) => ({...rest, value: parseFloat(value)}));
), but if you can't avoid it, you can't avoid it. :-)
Since you're mutating the objects, unless you have a very unusual use case, there's no reason to create a new array, and not doing so may also help with your performance issue:
/**
* @param records The record to transform.
* @returns The **same** array, objects are mutated in place.
*/
function transform(records: FromType[]): ToType[] {
for (let n = records.length - 1 ; n >= 0; --n) {
const record = records[n];
const result = record as any as ToType; // A brief lie...
result.value = parseFloat(record.value); // ...which is now true
}
return records as any as ToType[];
}
Even if you do need to create a new array, given that this function is mutating in place, it probably makes sense to have that be something the caller does (perhaps via slice
, which is very fast).