The altered closure variable ts remains undetectable

Check out the live demonstration

I made changes to the flag variable, but TypeScript did not recognize it. Could this be a coding issue?

function fn () {
  let flag = true

  function f () {
    // alter the value of flag
    flag = false
  }

  for (let i = 0; i < 10; i++) {
    // error: This condition will always return 'false' since the types 'true' and 'false' have no overlap.
    if (flag === false) { break }
    f()
  }

  return flag
};

fn()


Answer №1

For a detailed response to this query, refer to microsoft/TypeScript#9998.

The issue observed is not a bug but rather a TypeScript design limitation that is challenging to address easily. An illustration of functional code:

function fn() {
  let flag = true
  for (let i = 0; i < 10; i++) {
    if (flag === false) { break }
    flag = false;
  }
  return flag
};

In the provided example, the compiler recognizes flag as type boolean, a shorthand notation in TS for the union true | false. The compiler narrows down the apparent type of flag from true | false to just true after the initial assignment of true. However, within the loop scope, the reassignment to false resets the narrowing to

boolean</code inside the loop.</p>
<hr />
<p>Unfortunately, when refactoring the <code>flag = false
line into the body of f(), the compiler does not reset the narrowing post function call execution, resulting in an error due to incorrect assumption about flag's type.

The reason behind this behavior is the limitations in accurately and efficiently performing control flow analysis with closure mutations. Inline expansion for every function call would be impractical, leading to extended compile times, hindering performance.

As accuracy isn't achievable, the compiler relies on optimistic assumptions like assuming function calls have no impact on state. This approach saves compilation time but can lead to errors in scenarios where function calls do indeed alter state.

While there may be room for improvement in this area, at present, TypeScript struggles to track state mutations within function calls.


To prevent such erroneous errors when dealing with state-changing functions, refrain from narrowing flag's type altogether by adjusting its initial assignment as follows:

let flag = true as boolean;

This widens the type of the true value to true | false, keeping flag indeterminate throughout the scope according to the compiler.

Playground link to code

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to use lodash to group objects that contain nested objects?

Currently utilizing Typescript in conjunction with Lodash! Upon retrieving data from the database, here is the resulting output: [ { "unitPrice": 0.01, "code": "92365524", "description": "Broto gr ...

The user interface design transforms as a PDF file is being generated through html2pdf

I am experiencing an unusual problem while using html2pdf to convert an HTML page to a PDF file and download it. The conversion process is successful and the PDF file is downloaded without any issues. However, when I click on a button to generate the file, ...

Declaring a function type with a void parameter type in typescript

Embarking on my journey with ts and currently exploring TypeGraphQL. I came across something that caught my attention and seems unfamiliar to me: export declare type ReturnTypeFunc = (returns?: void) => ReturnTypeFuncValue; How should this type be unde ...

Formatting Time in Angular 2 Using Typescript

Upon reviewing my date source, I found the following: TimeR ="2017-02-17 19:50:11 UTC"; Within the HTML file, I implemented this code snippet <span class="text-lg">{{TimeR | date: 'hh:mm'}}</span> The current output displays the t ...

Retrieving information from a Kendo grid cell

I am working on a web application that utilizes Kendo Grid. How can I retrieve the values of the "Ticket No" from the selected checkboxes? https://i.stack.imgur.com/aPOje.png This is my code: var grid = $("#poGrid").data("kendoGrid"); grid.items().filte ...

Establish a Svelte and TypeScript "observe" script for developing vscode extensions

Hi there! As a newbie in TypeScript, Svelte, and VSCode extension development, I have my first question to ask ...

Setting a default value dynamically in a `select` control can be done by using JavaScript to

Upon subscribing to the HTTP server for data retrieval, my select control in Angular framework gets loaded with the received data. My objective is to set a default value that comprises three values from the server object separated by slashes ("/"), which r ...

Data is not displaying correctly in the Angular Material Table

I'm currently trying to build a mat table based on an online tutorial, but I'm facing a problem where the table appears empty even though I have hard coded data. As someone new to Angular and HTML/CSS, I'm struggling to understand why the ma ...

Tips for expanding the functionality of the d3-selection module using TypeScript

I am currently working on a project that involves TypeScript and d3. I have already installed 'd3' and '@types/d3', and my use of d3 looks like this: import * as d3 from 'd3'; const x = d3.scaleLinear ... Everything was goin ...

Getting the readonly-item type from an array in TypeScript: A step-by-step guide

Is it possible to create a readonly item array from a constant array? const const basicValueTypes = [{ value: 'number', label: 'Number' },{ value: 'boolean', label: 'Boolean' }]; type ReadonlyItemArray = ??? ...

Tips for calculating the total of keyup elements in an Angular application

There are "N" inputs in a formgroup that need to be summed: <input (keyup)="sum($event)" type="text" name="estoque_variacao{{i}}" class="form-control" id="estoque_variacao{{i}}" formControlName="estoque_variacao"> This is the Typescript code: sum( ...

When using videojs, I have the ability to include a Text Track event handler, however, there is currently no option to remove it

I implemented a listener for the 'cuechange' event on a Text Track and it's functioning correctly. However, I am unable to figure out how to remove this listener. I have attempted the instructions below to remove the listener, but it continu ...

There was an error linking the module "electron_common_features" which caused the Electron react test to fail

I recently developed a React Electron application using the electron-react-boilerplate template. I also added the @electron/remote package and made changes to the test case. However, upon running the command npm test, an error message stating No such modul ...

Tips for setting up chrome-app typings in Typescript 2

I am looking to eliminate the typings in our Typescript project. After successfully removing most typings dependencies with Typescript 2, I'm left with just one for chrome-app: https://github.com/uProxy/uproxy/compare/master...fortuna:master When usi ...

Encountered a React TypeScript issue stating that the type '{ ... }' cannot be assigned to the type 'IntrinsicAttributes & IntrinsicClassAttributes<...>'

Embarking on a new journey with a react typescript project, I encountered this puzzling error: Failed to compile. /Users/simon/Code/web/react-news-col/src/MainNewsFeed.tsx TypeScript error in /Users/simon/Code/web/react-news-col/src/MainNewsFeed.tsx(27,35 ...

The retrieval of cookies from the Response object is not possible with Typescript

While working on my google chrome extension, I implemented a post call that looks like this: public someapiCall(username: string, password: string) { var url = 'http://test.someTestServer.com/api/user/someApiCall'; let headers = new Hea ...

Implementing data waiting strategy in Vue component using TypeScript for rendering

When working with the first component, I encountered a scenario where I needed to open a new page using the router functionality: In Component_1.vue: let route = this.$router.resolve({ name: 'Schedule', params : { id: (this.schedule[0].schedule ...

Having trouble retrieving cookie in route.ts with NextJS

Recently, I encountered an issue while using the NextJS App Router. When attempting to retrieve the token from cookies in my api route, it seems to return nothing. /app/api/profile/route.ts import { NextResponse } from "next/server"; import { co ...

I am experiencing difficulties with TypeORM connecting to my Postgres database

Currently, I am utilizing Express, Postgres, and TypeORM for a small-scale website development project. However, I am encountering challenges when it comes to establishing a connection between TypeORM and my Postgres database. index.ts ( async ()=>{ ...

Apologies, the module "@org-name/package-name" could not be located

I've hit a roadblock for the past few days. My goal is to create a new npm package that wraps an API I've been developing. When bundling the package, everything seems to be fine in the /dist folder. However, when attempting to test it in a front ...