TypeScript Bits are small, easily digestible pieces of information to encourage TypeScript/JavaScript best practices. From beginner, to intermediate, to ninja, these bits are for you 😄
Estimated reading time : 2 minutes
Lets all be honest, side effects are terrible. They are especially terrible when working with a runtime that doesn't implicitly discern between mutable and immutable pre transpilation or compilation (like JavaScript). I have often found functions during code review where an Array or Object is manipulated in the subroutine returning the input Array or Object. Ideally, functions should remain pure.
A pure function is a function where the return value is only determined by its input values, without observable side effects...
So how do we enforce immutability pre-transpilation? Is that even possible in TypeScript?
let myNumArray : Array<number> = [0,1,2,3,4,5];
function removeFirstItem (inArray : Array<number>) : Array<number> {
inArray.shift();
return inArray;
}
removeFirstItem(myNumArray);
console.log(myNumArray); // prints [1, 2, 3, 4, 5]
let myNumArray : Array<number> = [0,1,2,3,4,5];
function removeFirstItem (inArray : Readonly<Array<number>>) : Readonly<Array<number>> {
inArray.shift(); // Property 'shift' does not exist on type 'readonly number[]'.(2339)
return inArray;
}
removeFirstItem(myNumArray);
console.log(myNumArray);
let myNumArray : Array<number> = [0,1,2,3,4,5];
function removeFirstItem (inArray : Readonly<Array<number>>) : Readonly<Array<number>> {
let numArrayOut : Array<number> = inArray.concat(); // returns new mutable array;
numArrayOut.shift();
return numArrayOut; //implicit cast to Readonly<T>
}
removeFirstItem(myNumArray);
console.log(myNumArray); prints [0, 1, 2, 3, 4, 5] untouched
- IMPORTANT The above code WILL RUN (in the "After" block), but if using TypeScript it will not compile
- The use of Readonly as a return value of a pure function is a design choice not a mandate. It is however good practice as it requires any chained operations or next use to explicitly create a new mutable instance to work with, further enforcing pure functions principles.
- This is very useful in function type definitions as it explicitly requires that the implementation be pure.
Visit the TypeScript Deep Dive for Readonly for more in-depth information!