Arrays are mutable
You read an element with its index, and you change it the same way: put the indexed element on the left of an assignment. Unlike a string, whose characters can't be replaced, an array can have its elements changed at any time.
let myArray = ["Hello world!", 32, false];
myArray[1] = "second element";
myArray[2] = -60;
console.log(myArray);
[ 'Hello world!', 'second element', -60 ]
The array keeps its length. Only the elements at indexes 1 and 2 were replaced, and the first stayed as it was. The assignment changed the array itself, not a copy.
Compound assignment
When the new value depends on the old one, use an operator such as +=. ages[1] += 5 reads the element at index 1, adds 5 and stores the result in the same slot. It means the same as ages[1] = ages[1] + 5, written once. The other compound operators work too: -=, *= and /=.
let ages: number[] = [14, 32, 50, 21];
ages[1] += 5;
ages[2] -= 10;
ages[3] *= 2;
console.log(ages);
[ 14, 37, 40, 42 ]
The right-hand side can be any expression of the right type, including one that uses other elements. ages[0] = ages[1] + ages[2] stores the sum of the second and third elements in the first slot. The right side is evaluated before the store, so the old value of ages[0] is simply discarded.
The types still apply
An element keeps the element type of its array. In a string[] you can only store strings, and in a number[] only numbers. Assigning the wrong kind of value is a compile-time error:
let nums: number[] = [1];
nums[0] = "x";
error TS2322: Type 'string' is not assignable to type 'number'.
Remember that the annotation is erased in the generated JavaScript. The compiler reports the error and still writes the file, so such a program would run and store the string. The check is there to help you, and you need to act on it.
The earlier example with myArray worked because TypeScript inferred its type as an array of strings, numbers and booleans, so replacing a number with a string was allowed.
Gotchas
- Two names, one array. Assigning an array to another variable copies the reference, not the contents. After
let b = a;andb[0] = 99;, bothaandbshow[ 99, 2, 3 ]. To get an independent copy, write[...a]. Changing the copy then leaves the original alone. constonly protects the name. Withconst frozen = [1, 2];, the assignmentfrozen[0] = 7;is allowed and gives[ 7, 2 ]. Only reassigningfrozenitself is an error.- Writing past the end grows the array, with a gap. If
ageshas four elements, thenages[6] = 1;gives it a length of 7, with two empty slots between. Node prints it as[ 14, 37, 40, 42, <2 empty items>, 1 ], and reading an empty slot givesundefined. TypeScript doesn't complain, so a wrong index here is easy to miss. +=on a missing element.ages[10] += 1readsundefined, andundefined + 1isNaN, so the slot ends up holdingNaN.- Indexes start at 0. The first element is at index 0. Changing index 1 changes the second element.
The lesson's exercise
The code begins with fruits, a string[] holding "mango", "kiwi" and "grapefruit", and ages, a number[] holding 14, 32, 50 and 21.
- Change the first fruit. The first item is at index 0, so assign to
fruits[0]. The new value must be a string, becausefruitsis astring[]. - Add 5 to the second age. The second item is at index 1. Use
+=, which reads the current 32, adds 5 and stores 37 in the same slot.
let fruits: string[] = ["mango", "kiwi", "grapefruit"];
let ages: number[] = [14, 32, 50, 21];
fruits[0] = "apple";
ages[1] += 5;
After these two lines, fruits is [ 'apple', 'kiwi', 'grapefruit' ] and ages is [ 14, 37, 50, 21 ]. The lesson prints nothing, so add a console.log yourself to see them.
Key takeaways
- Assign to
array[index]to replace an element. The array is changed in place. - Use
+=,-=,*=and/=to update an element from its current value. - The new value must match the array's element type, or the compiler reports an error.
- Variables that name the same array share it. Copy with
[...a]when you need independence. - Writing past the end leaves empty slots, and TypeScript doesn't warn you.