Readonly Typed Arrays in TypeScript
Published
A proposal to add support for built-in readonly typed arrays got rejected by the TypeScript team. This post shows how to build your own.
The issue calls out this type as a potential workaround:
export interface ReadonlyUint16Array extends Uint16Array {
readonly [n: number]: number;
};
The keen observer may notice that this only protects index access from mutation though, typed arrays have several methods for modifying the data as well like set
and fill
. For example:
const a: ReadonlyUint16Array = new Uint16Array(1);
console.log(a[0]); // 0
a.set([1], 0);
console.log(a[1]); // 1
This is what I came up with to properly protect typed arrays:
export interface ReadonlyUint16Array extends Omit<Uint16Array, 'copyWithin' | 'fill' | 'reverse' | 'set' | 'sort'> {
readonly [n: number]: number;
}
Which should give the following errors:
const a: ReadonlyUint16Array = new Uint16Array(1);
a.set([1], 0);
// Property 'set' does not exist on type 'ReadonlyUint16Array'
a[0] = 2;
// Index signature in type 'ReadonlyUint16Array' only permits reading.
Here are all the typed arrays for convenient copy and pasting:
export type TypedArrayMutableProperties = 'copyWithin' | 'fill' | 'reverse' | 'set' | 'sort';
export interface ReadonlyUint8ClampedArray extends Omit<Uint8ClampedArray, TypedArrayMutableProperties> { readonly [n: number]: number }
export interface ReadonlyUint8Array extends Omit<Uint8Array, TypedArrayMutableProperties> { readonly [n: number]: number }
export interface ReadonlyUint16Array extends Omit<Uint16Array, TypedArrayMutableProperties> { readonly [n: number]: number }
export interface ReadonlyUint32Array extends Omit<Uint32Array, TypedArrayMutableProperties> { readonly [n: number]: number }
export interface ReadonlyInt8Array extends Omit<Int8Array, TypedArrayMutableProperties> { readonly [n: number]: number }
export interface ReadonlyInt16Array extends Omit<Int16Array, TypedArrayMutableProperties> { readonly [n: number]: number }
export interface ReadonlyInt32Array extends Omit<Int32Array, TypedArrayMutableProperties> { readonly [n: number]: number }
export interface ReadonlyFloat32Array extends Omit<Float32Array, TypedArrayMutableProperties> { readonly [n: number]: number }
export interface ReadonlyFloat64Array extends Omit<Float64Array, TypedArrayMutableProperties> { readonly [n: number]: number }
export interface ReadonlyBigInt64Array extends Omit<BigInt64Array, TypedArrayMutableProperties> { readonly [n: number]: bigint }
export interface ReadonlyBigUint64Array extends Omit<BigUint64Array, TypedArrayMutableProperties> { readonly [n: number]: bigint }