question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Request: support old ES "with" statement

See original GitHub issue

I did not thoroughly search for this! I’m sorry, it’s pretty hard to search for such a common word, there were thousands of issues that use “with,” but I tried looking through the first few hundred.

Suggestion

TypeScript support (a restricted subset of) the old JavaScript keyword: “with.”

Use Cases

Simplifies code that accesses a large number of different, yet known keys of an object in quick succession.

Examples

const foo = {
    bar: "baz",
    qux: "foobar"
};

with ( foo ) {
    // introduces two new variables into scope
    // bar :: string
    // qux :: string
    console.log(bar, qux);
}
// bar : not in scope
// qux : not in scope

output:

const foo = {
    bar: "baz",
    qux: "foobar"
};

{
    console.log(foo.bar, foo.qux);
}

Checklist

My suggestion meets these guidelines:

  • This wouldn’t be a breaking change in existing TypeScript/JavaScript code
  • This wouldn’t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript’s Design Goals.

~ This is a runtime feature, but this is already a feature that was implemented in ECMAScript itself (at some point). Technically, it has not been removed. It is merely disallowed in strict mode.

I do not recommend supporting the actual ECMAScript “with” statement (I hate that the self/window/globalThis object is still global). Instead, I suggest that a very restricted subset is supported.

It would have to be very restrictive in order to not bring back the problems of the original “with.” Suggested restrictions to ensure code can still be typed and remain safe:

  • The object may only have known keys (string literals, no symbols, no numbers), it may not be an array.
  • The object must be contained in a variable, specifically one that is const (function calls can mutate non-const variables). (The variable restriction may be alleviated if the code is transpiled into a block with a variable assignment.)
  • (should not be done at global scope?)

It is very possible to transpile with to perfectly safe runtime code that can be guaranteed to be as safe as if one had explicitly accessed the object. It wouldn’t be hard if only supporting a subset, yet there are other implications to consider, such as performance, especially with nested with statements.

(And yes, this could also be used to create the most hellish spaghetti code you have ever seen.)

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:17
  • Comments:17 (4 by maintainers)

github_iconTop GitHub Comments

77reactions
johnsoncodehkcommented, Sep 4, 2021

I am the maintainer of the official Vue IDE plugin. Due to the particularity of the Vue template syntax, we need to use the with statement to make some very important performance improvements. Considering the number of Vue users, the benefits this brings will be huge. If TS can support this, we would be very grateful. 🙏

13reactions
johnsoncodehkcommented, Feb 8, 2022

@DanielRosenwasser Thank you for your attention to this issue!

For the below vue SFC code.

<template>
  <h1>{{ msg }}</h1>
  <button @click="count++">count is: {{ count /* type: number */ }}</button>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'

export default defineComponent({
  props: {
    msg: {
      type: String,
      required: true,
    },
  },
  setup() {
    const count = ref(0)
    return {
      count, // type: Ref<number>
    };
  },
});
</script>

We currently need at least these steps to generate virtual code to provide IDE support for script blocks and template blocks:

  1. Generate virtual <script> block script and provide to language service host
// ./virtual_script_code.ts
import { defineComponent, ref } from 'vue'

export default defineComponent({
  props: {
    msg: {
      type: String,
      required: true,
    },
  },
  setup() {
    const count = ref(0)
    return {
      count, // type: Ref<number>
    };
  },
});
  1. Use TypeScript type checker API or language service API to extract component instance type properties.
    • msg
    • count
    • $props
    • $data

This is the most time-consuming step, because calculating component instance type after updating the virtual_script_code.ts to the language service host needs to execute a very time-consuming syncHostData().

  1. Generate virtual <template> block script and provide to language service host
// ./virtual_template_code.tsx
import Component from './virtual_script_code.ts'

const componentInstance = new Component();

// component instance properties
let msg = componentInstance.msg;
let count = componentInstance.count;
let $props = componentInstance.$props;
let $data = componentInstance.$data;
// ...

{
  <h1 msg={ msg }></h1>
  <button onClick={ () => count++ }>count is: {{ count /* type: number */ }}</button>
}

(Note that the above process is simplified and is actually more complex.)


If TS support with statement, we can skip the step 2, avoid triggering syncHostData() in the process, and generate more efficient template virtual code.

// ./virtual_template_code.tsx
import Component from './virtual_script_code.ts'

const componentInstance = new Component();

with (componentInstance) {
  <h1 msg={ msg }></h1>
  <button onClick={ () => count++ }>count is: {{ count /* type: number */ }}</button>
}

In our case, we only need language service support in IDE, no need emit js support.

Hope the explanation is clear enough.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Army and Air Force LES Requests
Army and Air Force LES Requests: Leave and earning statements from January 1992 and later can be requested through your servicing finance office....
Read more >
Request for a Social Security Statement (SSA-7004)
If you were unable to create or encountered a problem with your my Social Security account, you may visit a local office or...
Read more >
How To Request A VA Home Loan Certificate Of Eligibility (COE)
This is the first step in getting a VA-backed home loan or Native American Direct ... Gather the information you'll need to request...
Read more >
7. Simple statements — Python 3.11.1 documentation
The syntax for simple statements is: Expression statement. ... creating a new object and assigning that to the target, the old object is...
Read more >
Obtaining service for your Apple product after an expired ...
Find out which products are vintage: Mac; iPod; iPhone; iPad; Beats; Apple Watch (Apple Retail Store only) ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found