dabuside
dabuside

Reputation: 113

How to add a extra property to array with typescript

I want to add an extra property to an array, but I get trouble with declaring it.

small part

const arr: string[] & {key: number} = ['123'];//ts error  Property 'key' is missing
arr.key = 10;

large part

I need to group arr by index then sort it by value

add an index to array property will be a convenience if using Object.values but not Object.entries. I know there are many approaches to do this, but I think it's much easier if I am using plain js

type Arr = {index: number, value: number};
const arr:Arr[] = []
arr.push({
    index: 10,
    value: 2
})
arr.push({
    index: 10,
    value: 1
})
arr.push({
    index: 10,
    value: 3
});
arr.push({
    index: 20,
    value: 100
});
arr.push({
    index: 20,
    value: 50
});
arr.reduce<Record<string, Arr[] & {index: number}>>((prev, curr) => {
    if(!prev[curr.index]){
        prev[curr.index] = [];//ts error Property missing
        prev[curr.index].index = curr.index;
    }
    prev[curr.index].push(curr);
    prev[curr.index].sort((a,b) => a.value - b.value);//or some insertion sort algorithm.
    return prev;
},{})

Upvotes: 6

Views: 4163

Answers (2)

SparkFountain
SparkFountain

Reputation: 2270

Please consider the accepted answer instead.

In your small part example, the type declaration string[] & {key: number} can never be satisfied because an array of strings cannot be the same as an object with key property.

Concerning your large part example, what exactly are you trying to achieve? If you say you want to group an array by an index, and then sort it by value, do you mean that the index is kind of your primary sort criterion and value the secondary criterion? In that case, I'd suppose you write your own sorting function that takes both values into account. You'll find an example in this Stackoverflow thread.

Upvotes: 1

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249506

An array literal can't by itself satisfy the intersection, the simplest way you could do it is to use Object.assign which returns an intersection of its arguments:

const arr: string[] & {key: number} = Object.assign(['123'], {
    key: 10
});

And in your bigger example, the same could be used:

arr.reduce<Record<string, Arr[] & {index: number}>>((prev, curr) => {
    if(!prev[curr.index]){
        prev[curr.index] = Object.assign([], {
          index: curr.index
        })
    }
    prev[curr.index].push(curr);
    prev[curr.index].sort((a,b) => a.value - b.value);//or some insertion sort algorithm.
    return prev;
},{})

playground link

Upvotes: 10

Related Questions