3

I want the typescript compiler to throw an 'Object is possibly 'undefined'' error when trying to directly access any element of the array if the array is not pre-checked for emptiness, so that you always have to check that element for undefined, for example, using an optional chaining

If it is pre-checked that the array is not empty, then you need to be able to access its elements as usual, without the need to check its elements for undefined

I need this in order to be sure that the array is not empty, so if it is empty, then access to any of its elements will immediately return undefined then chaining will not continue and there will be no possible errors like cannot read property of undefined

How do i do this?

Code example, maybe it will make my question clearer

interface Element {
  a: {
    aa: string;
    bb: string;
  };
  b: {
    aa: string;
    bb: string;
  };
}

const element: Element = {
  a: { aa: "aa", bb: "bb" },
  b: { aa: "aa", bb: "bb" },
};

type ElementArray = Element[];

const array: ElementArray = [element, element];
const emptyArray: ElementArray = [];

const getFirstAWithoutLengthCheck = (array: ElementArray) => {
  return array[0].a; // i want the typescript compiler to throw an 'Object is possibly 'undefined'' error here
};

const getFirstAWithLengthCheck = (array: ElementArray) => {
  if (array.length) {
    return array[0].a; // shouldn't be any errors
  }
  return null;
};

const getFirstAOptChaining = (array: ElementArray) => {
  return array[0]?.a; // shouldn't be any errors
};

// will throw error cannot read property a of undefined, so we need to use
// optional chaining or length check in this function, but typesript is not requiring it
console.log(getFirstAWithoutLengthCheck(array)); // aa
console.log(getFirstAWithoutLengthCheck(emptyArray)); // crash!

// checking array length, access to first element should work as usual, no errors
console.log(getFirstAWithLengthCheck(array)); // aa
console.log(getFirstAWithLengthCheck(emptyArray)); // null

// optional chaining, no errors
console.log(getFirstAOptChaining(array)); // aa
console.log(getFirstAOptChaining(emptyArray)); // undefined
3

2 Answers 2

3

As commented by @Roberto Zvjerković, you need to use noUncheckedIndexedAccess compiler flag.

Playground (The link has noUncheckedIndexedAccess flag turned on).

However, you need to use instead of if (array.length), you need to do if (array[0]). It is because, even if the length is non-zero, it does not ensure that the elements are "non-undefined". If the array were array = [undefined], it should have given runtime error. It is irrespective of the type of array if it can contain undefined or not.

Sign up to request clarification or add additional context in comments.

Comments

0

I managed to make TypeScript throw an error in the first example and not throw an error in the third one but it sadly gives you the undefined error in the second example. Hope this helps you:

interface Element {
  a: {
    aa: string;
    bb: string;
  };
  b: {
    aa: string;
    bb: string;
  };
}

const element: Element = {
  a: { aa: "aa", bb: "bb" },
  b: { aa: "aa", bb: "bb" },
};

type ElementArray = [] | [Element] | [Element, ...Element[]];

const array: ElementArray = [element, element];
const emptyArray: ElementArray = [];

const getFirstAWithoutLengthCheck = (array: ElementArray) => {
  return array[0].a; // i want the typescript compiler to throw an 'Object is possibly 'undefined'' error here
};

const getFirstAWithLengthCheck = (array: ElementArray) => {
  if (array.length) {
    return array[0].a; // shouldn't be any errors
  }
  return null;
};

const getFirstAOptChaining = (array: ElementArray) => {
  return array[0]?.a; // shouldn't be any errors
};

// will throw error cannot read property a of undefined, so we need to use
// optional chaining or length check in this function, but typesript is not requiring it
console.log(getFirstAWithoutLengthCheck(array)); // aa
console.log(getFirstAWithoutLengthCheck(emptyArray)); // crash!

// checking array length, access to first element should work as usual, no errors
console.log(getFirstAWithLengthCheck(array)); // aa
console.log(getFirstAWithLengthCheck(emptyArray)); // null

// optional chaining, no errors
console.log(getFirstAOptChaining(array)); // aa
console.log(getFirstAOptChaining(emptyArray)); // undefined

TypeScript playground Ignore the error on element, TypeScript playground thinks that element is a DOM element

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.