Repository navigation
Infer RegExp for regular expression literals under isolatedDeclarations - #65419
Andrii Drok (andriidrok1) wants to merge 1 commit into
Conversation
…tions` The pseudochecker had no case for regular expression literals, so a declaration like `export const re = /ab+c/g` reported TS9010 under `--isolatedDeclarations` even though its type can only be the global `RegExp`. Add a `PseudoTypeKindRegExp` pseudotype returned for regex literals and serialize it through the checker's `globalRegExpType`, so a file that shadows `RegExp` still gets a correct `globalThis.RegExp` reference. Fixes microsoft#58383 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues were identified for the regular-expression inference change.
No open issues 🎉
What changed in this PR
Addresses #58383 by allowing the native TypeScript compiler to infer RegExp from regular expression literals under --isolatedDeclarations, including when a local declaration shadows RegExp.
Changes:
- Adds a dedicated regular-expression pseudo-type and literal inference case.
- Maps the pseudo-type to the global
RegExptype for declaration emit. - Adds regression coverage and baselines for declarations, const contexts, returns, defaults, and shadowing.
| File | Description |
|---|---|
tsc/testdata/tests/cases/compiler/isolatedDeclarationsRegExp.ts |
Adds regression cases for regex inference and shadowing. |
tsc/testdata/baselines/reference/compiler/isolatedDeclarationsRegExp.types |
Records expected inferred types. |
tsc/testdata/baselines/reference/compiler/isolatedDeclarationsRegExp.symbols |
Records expected symbol bindings. |
tsc/testdata/baselines/reference/compiler/isolatedDeclarationsRegExp.js |
Records JavaScript and declaration output. |
tsc/internal/pseudochecker/type.go |
Defines the RegExp pseudo-type kind and singleton. |
tsc/internal/pseudochecker/lookup.go |
Recognizes regular expression literals during inference. |
tsc/internal/checker/pseudotypenodebuilder.go |
Converts the pseudo-type using the global RegExp type. |
Review effort: Balanced
|
@microsoft-github-policy-service agree |
|
I'm not sure why this issue was marked "help wanted"; this issue still requires discussion and has future implications |
|
Understood. For context, the inference here is the one discussed in #58383: a plain |
Fixes #58383
Problem
Under
--isolatedDeclarations, a declaration initialized with a regular expression literal reports TS9010/TS9012/TS9013 even though the type can only ever beRegExp:typeFromExpressionin the pseudochecker has cases for numeric, string, bigint and boolean literals but none forRegularExpressionLiteral, so it falls through to "needs inference". The checker itself always types the literal as the globalRegExp(checkRegularExpressionLiteral).Change
pseudochecker: aPseudoTypeKindRegExpkind (a singleton likePseudoTypeString) and aRegularExpressionLiteralcase returning it. There are no regex literal types, so it is not wrapped inMaybeConstLocation: the result isRegExpin const contexts too.pseudotypenodebuilder: the new kind serializes astypeToTypeNode(globalRegExpType)and maps toglobalRegExpTypeinpseudoTypeToType.Serializing the global type instead of a hand-made
RegExpidentifier is what handles the shadowing concern raised in the issue: when a file declares its ownRegExp, the node builder emitsglobalThis.RegExp, the same way declaration emit already refers to any shadowed global. That stays syntactically determinable for isolated tools, since the shadowing declaration or import is in the same file.Notes
noLib,globalRegExpTypeis the empty object type, so the emitted type is{}, the same as non-isolated declaration emit in that configuration.Tests
isolatedDeclarationsRegExp.tscoversconst/let/var, object literal properties, anas constobject with a regex array, a function and an arrow return, class fields (including an optional one), parameter defaults followed by a required parameter, and two files that shadowRegExp(a class and a type alias). Output:Without the change the same test reports 17 isolatedDeclarations errors (TS9010, TS9012, TS9013, TS9025) and no declarations for those initializers. No other baselines change.
npx hereby test,lint,check:formatandtidypass with no diff.I used Claude Code to draft this change; I reviewed and tested every line and will handle review feedback myself.
🤖 Generated with Claude Code