coordinates
is defined as a tuple type in Typescript. Tuples inherit from arrays, and the methods available on tuples actually originate from Array<T>
. While this setup is convenient, when these methods are called, they return arrays instead of tuples. So, if you apply the map
method to a tuple with 3 elements, you might anticipate a tuple output with 3 elements, but it will actually be an array.
To address this, a simple solution is to use type assertion to inform the compiler that the result will be a tuple containing 3 numbers:
this.coordinates = coordinates.map((coordinate) => {
return Math.round(parseFloat(coordinate) * 100) / 100;
}) as [number, number, number];
Edit
An alternative approach involves extending the global interface of Array
to accurately define the type of the result from the map
operation:
interface Array<T> {
// Support for up to 3 tuple items, can be expanded
map<U>(this: [T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U];
map<U>(this: [T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U];
map<U>(this: [T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U];
}
class Point {
coordinates: [number, number, number];
constructor(coordinates: [string, string, string]) {
// Now functions as intended
this.coordinates = coordinates.map((coordinate) => {
return Math.round(parseFloat(coordinate) * 100) / 100;
});
}
}
This GitHub issue contains a valuable discussion on this topic.