Repository: TypeScript
Issue: Design Meeting Notes, 4/26/2024
Labels: Design Notes


# RegExp Syntax Checking and Annex B

* Background: Took a PR that started checking syntax on regular expressions.
    * Was too breaky. Too much valid code was being rejected.
    * Lots of regular expressions take advantage of ECMAScript's "Annex B" grammar/behavior.
* What is Annex B?
    * Features/exceptions of ECMAScript for web browsers - they encode web reality.
* Annex B has an entire section for expanding what is allowed in regular expressions.
    * Allows
    * Quantifiers after look-arounds
    * Allows `]`, `{`, and `}` as bare pattern characters
    * `\c` allowed when missing control sequence (`\cb` is the ordinary case, but you have `\c` which is just `c` - kind of an identity escape)
    * Identity-escapes allowed (`\a` = `a`)
    * `\1` even when backreferences don't exist (like an identity escape - just turns into `1`)
    * Allows legacy octal escapes
    * Allows invalid ranges in character classes `[\w-_]`
* These don't kick into effect in Unicode modes.
* Some of these are bad - what do we want to error on regardless of Annex B rules?
    * Invalid pattern characters - `/]{}/`?
        * Maybe
    * Identity escapes?
        * Lots of things that seem like they're using features that are only in other regex modes (like Unicode mode).
            * But people often proactively escape punctuation.
        * Maybe just ASCII letters?
            * That seems better.
    * Invalid backreferences?
        * `\2` - people usually mean for this to be a backreference, but this will be interpreted as an octal escape!
    * Back-references in character classes?
        * `[\1]` - this is a backreference, but it's in a character class - it's just an octal `1` in a character class.
        * When people write `[^\1]+` usually people want to say "anything other than the first capture" - but that's `(?:(?!\1).)`.
    * Invalid ranges?
        * Character classes used as range bounds.
        * `/\w-_]/` is treated the same as `/[-\w_]/`.
    * Wrong target?
        * Probably okay to keep erroring? People can use a `// @ts-ignore`
* Can we offer editor-specific suggestion diagnostics for these?
    * Especially stuff like invalid ranges.
* A big component of this not feeling like noise

## `--skipCheck`/`--noCheck`

* Last time we discussed `skipCheck`, we said we would make it an API-only feature for now because there was no way we could serve user scenarios around it. Needed more thought.
* Should we disallow generating `.tsbuildinfo` files when `skipCheck` is enabled?
    * Right now it is not just API-only, but it's internal-only.
    * So right now it's just 
* We have another PR to block `.tsbuildinfo` for other internal-only options being passed in externally.
    * Might not have to do it for all internal options - the point is really just about `skipCheck`'s behavior.
* But nobody can pass this in.
* What is the problem statement?
    * Do we need to do a defensive check to make sure `tsbuildinfo` is generated as `undefined`? Or can it just generate an invalid `.tsbuildinfo`?
*  We will address this problem when it becomes public.

## Strict Readonly

#58296

* Name bike-shedding?
    * `--strictReadonly` - it's not a strict flag though.
    * `--enforceReadonly` - were we not already enforcing readonliness?
* New developments since last discussed - methods are now excluded from these checks.

  ```ts
  interface Base {
      foo(): void;
  }

  interface Item extends Base {
      name: string;
  }

  interface ReadonlyItem extends Base {
      readonly name: string;
  }

  declare let item1: ReadonlyItem;
  declare let item2: Readonly<Item>;

  item1 = item2; // error?
  ```
    * Rarely do you want to think of `readonly`-ness on *methods* - usually it's state.
    * Methods are rarely mutated.
        * Sometimes people bind methods and re-assign in the constructor - but they're not meant to be written to again anyway.
    * In a sense, you can think of "mutable" methods as being implicitly `readonly` for compatibility checks.