Is it feasible to stop closure from capturing external variables in TypeScript?

Imagine I have the following piece of Typescript code:

const a = 456
const b = () => a 

Is there a way to make the Typescript compiler detect and flag an error or warning during compilation indicating that function b is accessing an external variable a?

P/S: I am interested in exploring the technical feasibility of such a feature, rather than reasons why it may not be advisable.

Answer №1

Following the guidance of Eugene, I took it upon myself to create an eslint plugin specially designed for this purpose. By installing and setting up the plugin, you can analyze code like the example below:

const x = 123
// eslint-no-closure
const f = () => x 

which will produce the following output:

file.ts
  1:7   error  declared variable x referenced in an `eslint-no-closure` function  no-closure/no-tagged-closures
  3:11  error  function tagged with `eslint-no-closure` closes variables: x       no-closure/no-tagged-closures
  3:17  error  reference to variable x in an `eslint-no-closure` function         no-closure/no-tagged-closures

✖ 3 problems (3 errors, 0 warnings)

The default report may be a bit lengthy, but it can be simplified if needed.

Answer №2

If you're searching for guidance on configuring a compiler, consider exploring linters instead.

One popular option is ESLint, which offers rules like no-shadow:

Shadowing occurs when a local variable shares the same name as a variable in its surrounding scope. The goal of this rule is to prevent shadowed variable declarations.

The purpose of avoiding such configurations within a compiler infrastructure is due to the extensive responsibilities compilers already hold. Compilers focus on parsing source code and generating targeted output efficiently, making additional tasks such as readability checks too burdensome. This is where tools like linters come into play - they enforce coding standards and readability by applying specific rules to your codebase.


UPDATE: My initial understanding of the question was incorrect; it's not about shadowing variables but rather accessing them from higher scopes.

To address this, creating a custom plugin for a linter may be a viable solution.

For instance, developing a unique rule for ESLint - reference to developer guide.

The concept involves crafting your own rule (function) that returns a Visitor for AST nodes. By traversing the AST, you can manage information, save variable references within scopes, and detect unauthorized access attempts across different scopes (this is a simplified explanation).

Answer №3

To ensure lexical visibility only within a specific scope, one approach is to write the function f in a separate file. This method prevents other variables from the original file from being accessible. The same concept can be applied in JavaScript like so:

// main.ts
import { f } from './f'
const x = 123;
// perform operations with f and x
// f.ts
export const f = () => {
  console.log('running f');
  // attempting to access x (or any variable from the original file)
  // will result in a TypeScript error
};

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

Managing animations with multiple components in Angular 2+

I am currently developing an Angular application that will utilize a series of Modals in a wizard-style setup. For this project, I am utilizing the Angular-cli tool. Below is the code snippet showing how I have set up my animations: animations:[ t ...

"Techniques for extracting both the previous and current selections from a dropdown menu in Angular 2

How can I retrieve the previous value of a dropdown before selection using the OnChange event? <select class="form-control selectpicker selector" name="selectedQuestion1" [ngModel]="selectedQuestion1" (Onchange)="filterSecurityQuestions($event.t ...

Unable to call a component's method from a different component in Angular 7

How can I call the toggleSidebar() method of the SidebarComponent from the HeaderComponent using the callToggleSidebarOnToggleSidebarBtn() method? I am encountering an error that I cannot comprehend. What is the correct way to use a method of one component ...

Issue in Typescript: The type 'RegExpMatchArray' cannot be assigned to a parameter of type 'string'

Here is the code snippet I am working with: import { persistState } from 'redux-devtools'; const enhancer = compose( applyMiddleware(thunk, router, logger), DevTools.instrument(), persistState( window.location.href.match(/[?&]debu ...

Encountering Issue: Unable to locate control with the given name in Angular when generating Dynamic Form with FormGroup

As a beginner in Angular, I aim to develop a dynamic Survey Form that can adjust its questions and input types based on the area. These changes are fetched as JSON data through API calls. Here is the relevant code snippet: .ts File export class Maintenan ...

Issue: When attempting to read the length of a property in Angular 6, a TypeError is being thrown because the property is

Unable to retrieve values from an array using the TS code below: this.dataservice.get("common/public/getAllCategories", null).subscribe(data => { //console.log('categories'+JSON.stringify( data)); this.categoriesarray = data; }); var ...

Leveraging Global Variables for Validation in Angular (Angular 10)

I am currently creating a form in Angular 10 which involves the use of validators. Specifically, I have been utilizing the Validators.min() method within my form... Instead of manually inputting the value '100' in the Validators.min('100&ap ...

TSX: Interface Definition for Nested Recursive Array of Objects

I'm having trouble making my typescript interface compatible with a react tsx component. I have an array of objects with possible sub items that I need to work with. Despite trying various interfaces, I always run into some kind of error. At the mome ...

Is it possible to implement a different termination condition when using *ngFor in Angular 2?

After countless hours of searching on Google, I have yet to discover a method for implementing an alternative stop condition for loops created with the *ngFor directive. By default, *ngFor loops end with this condition: index < array.length. Is there a ...

Join the nested Observables array

I have an array that holds objects, each containing two properties where one is an observable value. let myArray = [{def: 'name1', value: EventEmitter_}, {def: 'name2', value: EventEmitter_}] My goal is to subscribe to the observables ...

The custom form input in Angular2 is throwing an error because it is trying to access the property 'name' of an

Upon switching to the latest Angular version 2 final, I encountered the following error Uncaught TypeError: Cannot read property 'name' of undefined This is my customized input import { Component, EventEmitter, Provider, forwardRef } from &a ...

Issues arise in Angular 4 when the "Subscribe" function is repeatedly invoked within a for/switch loop

My array of strings always changes, for example: ["consumables", "spells", "spells", "consumables", "spells", "consumables", "spells", "characters", "characters", "consumables"] I iterate through this array and based on the index, I execute different .su ...

Best practices for updating the value of a specific key within an object that contains recursion in JavaScript/TypeScript

I have a tree component that uses the following data structure type TreeNode = { id: string, parentId: string, renderer: () => React.ReactNode, expanded: boolean, children?: Array<TreeNode>, } Now, I am looking to add functionality for ...

Is it possible to dynamically assign a template reference variable to a newly created DOM element in TypeScript?

After creating a DOM element with this.document.createElement('h1'), I am looking to insert the element into a section tag using a template reference variable (myTRF), similar to the example below: <section> <h1 #myTRF>This is my he ...

Unable to retrieve React state within the callback function

As I work with the following components: const ParentComponent: React.FC = () => { // Setting newType to some value within the code const [newType, setNewType] = useState<any>(undefined); // Enabling addEdge to true in another part o ...

What is the best way to include a non-data custom attribute in a TSX template without any value?

Currently, I am working on a React component with Typescript. The initial code looks like this.... const NameFormatter = React.createClass({ render() { return ( <div> <div className="dataset-name"> ...

When Angular 5 is loaded, the select list on the page will automatically display the matching option that

I am currently working on a form that is read-only and showcases data retrieved upon loading the page. One of the sections in this form includes an IsActive dropdownlist with options True or False. I have set up my model property isActive to bind with the ...

The Azure GraphQL serverless function encountering an issue with the Cosmos DB connection, displaying an

After developing a serverless GraphQL API function using Azure functions and connecting it to Cosmos DB, I have encountered an issue with "Invalid URL" that has been puzzling me for a week. Despite running the graphql function locally without any problems, ...

"Angular application experiencing navigation blockage due to multiple concurrent HTTP requests using RxJS - Implementation of priority-based cancel queue

I've come across similar threads, but I have yet to find a suitable solution for my specific issue. Situation: Currently, I'm navigating on both the server side and client side simultaneously. This entails that every frontend navigation using ro ...

What is the process for passing input values to a dynamic Angular component?

https://i.sstatic.net/hghse.png My goal is to develop a dynamic filtering system where users can specify multiple attributes and their corresponding values to filter a list of components. The dynamically added component includes two dropdown menus: one fo ...