ยท best practices

Safer Array Access with TypeScript 4.1

The `noUncheckedIndexedAccess` compiler option in TypeScript helps catch potential errors when accessing arrays or tuples with undefined or out-of-bounds indices. Enabling this option ensures that developers handle cases where indexed accesses can result in undefined values.

The noUncheckedIndexedAccess compiler option is designed to help catch potential errors caused by accessing arrays or tuples with possibly undefined or out-of-bounds indices. When this option is enabled, TypeScript assumes that indexed accesses can result in undefined values and requires developers to handle such cases explicitly.

Contents

Potential errors with array ranges

For example, consider the following code:

type User = {
  name: {
    firstName: string;
    lastName: string;
  };
};
 
const array: User[] = [];
const value = array[0];
 
console.log(typeof value); // "undefined"
console.log(value.name.firstName); // TypeError: Cannot read properties of undefined

If noUncheckedIndexedAccess is disabled, TypeScript assumes that value will always yield a User, even though array is empty. This can result in a runtime error when trying to access an undefined value.

Limitations of checking array length

Checking the array length alone is not sufficient to ensure code safety because arrays can have a length without containing any values, as demonstrated by the following code:

type User = {
  name: {
    firstName: string;
    lastName: string;
  };
};
 
const array: User[] = new Array(1);
 
if (array.length === 1) {
  const value = array[0];
  console.log(typeof value); // "undefined"
  console.log(value.name.firstName); // TypeError: Cannot read properties of undefined
}

Using noUncheckedIndexedAccess for code safety

Enabling the noUncheckedIndexedAccess option in your TypeScript configuration provides code safety by flagging potential undefined array or tuple accesses with a TS18048 error. To handle such cases and prevent crashes, you can use the optional chaining operator (?.) in TypeScript:

type User = {
  name: {
    firstName: string;
    lastName: string;
  }
}
 
const array: User[] = new Array(1);
 
if (array.length === 1) {
  const value = array[0];
  console.log(typeof value); // "undefined"
  console.log(value?.name.firstName); // undefined
}

Preventing errors with index signatures

Enabling noUncheckedIndexedAccess provides an additional advantage when working with index signatures. Index signatures allow arbitrary property names, as demonstrated in the options object below. With the compiler checking index access, you can avoid type errors and ensure safer code execution:

type Option = {
  // Index Signature
  [propName: string]: {
    name: string;
  };
};
 
function logOption(options: Option, key: string) {
  console.log(options[key]?.name);
}
 
logOption({}, 'key-does-not-exist');
Back to Blog