skip to Main Content

I’m trying to investigate why there is a runtime error when I called article.posts[0].title

I have post and posts and I want to call the first post of article (posts[0].title).
typescript assume I have posts size greater than 0 and doesn’t throw any error.

type Post = {
    title: string
    url: string
}

type Posts = Maybe<Array<Post>>

type Article = {
   posts: Posts
}

and global type

type Maybe<T> = T | null;

is there a typescript rule, eslint plugin or editor plugin that can detect this issue?

const article: Article = {
    posts: [],
}

article.posts?.[0].url

the final and correct code should be

const article: Article = {
    posts: [],
}

article.posts?.[0]?.url

thank you in advance.

error image

2

Answers


  1. In Short, To make typescript compatible with JavaScript.

    1. TypeScript aims to be a useful tool for JavaScript developers and doesn’t want to introduce behavior that significantly deviates from JavaScript. In JavaScript, accessing an index that is out of bounds simply returns undefined without throwing an error. TypeScript, by default, maintains this behavior.

      const array = [];
      array.indexOf['anyValue'] = 'test';
      console.log(array.indexOf.anyValue);
      // This is valid javascript code.
    2. Typescript checks types at compile time. At runtime, we are running javascript code where all types are removed. Let’s say array has dynamic length. you are adding/removing elements at runtime. TypeScript cannot check out of bound error at runtime. As typescript only checks at compile time.

    To add out of bound check, this is one possible solution:
    Use if condition.

    if(article.posts.length>0){
    article.posts[0].url; // access now
    } 
    

    Code example credit goes to sjahan

    Login or Signup to reply.
  2. Try accessing the array at index with at:

    const arr: string[] = [];
    const x = arr.at(0).toUpperCase();
    

    Here you can see a playground.

    Mind that it won’t check the index or the array length, but it will force you to check if the element exists before accessing it.

    The above code does not compile:

    Object is possibly ‘undefined’.(2532)

    While the following does compile:

    const arr: string[] = [];
    const x = arr.at(0)?.toUpperCase();
    

    In other words, the type of arr[0] is string, while the type of arr.at(0) is string | undefined.

    A good practice could be never accessing an array with the square brackets notation, but:

    • use .at(...) to access specific indices of the array
    • use functional methods like .map, .filter, .reduce and so on to iterate over the array
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search