Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c44a057
Type Inference for Regular Expressions
graphemecluster Oct 17, 2024
c435526
Fix Incorrect Disjunction Alternative Visibility
graphemecluster Nov 4, 2024
24c16f9
Add Test Cases for Duplicate Capturing Group Name
graphemecluster Nov 4, 2024
13cfe15
Performance optimization: Reduce type creation
graphemecluster Nov 6, 2024
6aeac05
Fix incorrect type for `/{0?/` etc. in non-Unicode mode
graphemecluster Nov 7, 2024
b828249
Fix: `i` modifier is not removed if no flags are added
graphemecluster Nov 7, 2024
bd74623
Remove more redundant literals esp. `"" | string`
graphemecluster Nov 7, 2024
a6e0b98
Fix: Incorrect characters included for `/\c/` & `/[\c]/` in Annex B
graphemecluster Nov 8, 2024
a31ddcb
Refactor: Rename variables and modify type of reduced union
graphemecluster Nov 8, 2024
42a6568
Refactor: Fast path character classes
graphemecluster Nov 9, 2024
9ce54aa
Refine types for cases where the cross product size is too large
graphemecluster Nov 9, 2024
bb0e808
Refactor: Type `RegularExpressionAnyString` as a unique symbol for be…
graphemecluster Nov 9, 2024
524f291
Expand test cases in `regularExpressionLiteralTypes.ts`
graphemecluster Nov 9, 2024
48f86ff
Fix: missing `"-"` in `/[+-]/`
graphemecluster Nov 9, 2024
3ddc5da
Mark `RegExpDigits` as character class (for fast path)
graphemecluster Nov 9, 2024
9dc953c
Correct lib types & Refine type checking test case
graphemecluster Nov 10, 2024
0cf763d
Separate type checking test case into 2 files which tests for differe…
graphemecluster Nov 10, 2024
53425e5
Add test case for `String#matchAll`
graphemecluster Nov 10, 2024
12e875b
Collapse consecutive string types in template literals
graphemecluster Nov 10, 2024
5dfdb56
Merge remote-tracking branch 'upstream/main' into regex-type-infer
graphemecluster Nov 10, 2024
09ad9c3
Fix up all baselines
graphemecluster Nov 10, 2024
61fc428
Fix up all self check errors
graphemecluster Nov 10, 2024
402760c
Separate the type checking test case further
graphemecluster Nov 10, 2024
99355c0
Temporarily exclude `RegExp` & `RegExpExecArray` from `checkNoTypeArg…
graphemecluster Nov 10, 2024
80dd5d0
Revert "Temporarily exclude `RegExp` & `RegExpExecArray` from `checkN…
graphemecluster Nov 10, 2024
b251992
Fix self check in a more ugly way due to build issue
graphemecluster Nov 10, 2024
5bd7951
Temporarily slience a few `no-unnecessary-type-assertion` lint lines …
graphemecluster Nov 10, 2024
037ef8e
Fix minor incorrect fix in self check
graphemecluster Nov 10, 2024
e51e144
Temporarily shrink type checking test case due to timeout
graphemecluster Nov 10, 2024
2989429
Inline `RegularExpressionAnyString` to avoid `export` keywords in `ty…
graphemecluster Nov 12, 2024
8cc6840
Keep `RegularExpressionAnyString` but export as internal
graphemecluster Nov 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Collapse consecutive string types in template literals
  • Loading branch information
graphemecluster committed Nov 10, 2024
commit 12e875b46deeed14607b16e4f7b0ac944b59e393
11 changes: 9 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18366,6 +18366,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
const newTypes: Type[] = [];
const newTexts: string[] = [];
let prevIsStringType = false;
let text = texts[0];
if (!addSpans(texts, types)) {
return stringType;
Expand Down Expand Up @@ -18398,8 +18399,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
text += texts[i + 1];
}
else if (isGenericIndexType(t) || isPatternLiteralPlaceholderType(t)) {
newTypes.push(t);
newTexts.push(text);
if (!text && prevIsStringType && t === stringType) {
// Collapse consecutive `${string}${string}`
}
else {
newTypes.push(t);
newTexts.push(text);
prevIsStringType = t === stringType;
}
text = texts[i + 1];
}
else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
regularExpressionTypeCheckingReplace.ts(18,33): error TS1503: Named capturing groups are only available when targeting 'ES2018' or later.
regularExpressionTypeCheckingReplace.ts(18,45): error TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type '(match: `foo${string}`, id: string, index: number, input: `${string}foo${string}${string}`, capturingGroups: [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]) => `foo${string}`' is not assignable to parameter of type 'string | StringReplaceCallbackSignature<[`foo${string}`, string], { id: string; }>'.
Type '(match: `foo${string}`, id: string, index: number, input: `${string}foo${string}${string}`, capturingGroups: [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]) => `foo${string}`' is not assignable to type 'StringReplaceCallbackSignature<[`foo${string}`, string], { id: string; }>'.
Argument of type '(match: `foo${string}`, id: string, index: number, input: `${string}foo${string}`, capturingGroups: [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]) => `foo${string}`' is not assignable to parameter of type 'string | StringReplaceCallbackSignature<[`foo${string}`, string], { id: string; }>'.
Type '(match: `foo${string}`, id: string, index: number, input: `${string}foo${string}`, capturingGroups: [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]) => `foo${string}`' is not assignable to type 'StringReplaceCallbackSignature<[`foo${string}`, string], { id: string; }>'.
Target signature provides too few arguments. Expected 5 or more, but got 4.
regularExpressionTypeCheckingReplace.ts(24,5): error TS18048: 'capturingGroups' is possibly 'undefined'.
regularExpressionTypeCheckingReplace.ts(24,21): error TS2339: Property 'id' does not exist on type 'string | number | { [name: string]: string | undefined; }'.
Expand Down Expand Up @@ -48,8 +48,8 @@ regularExpressionTypeCheckingReplace.ts(37,21): error TS2339: Property 'foo' doe
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2769: No overload matches this call.
!!! error TS2769: The last overload gave the following error.
!!! error TS2769: Argument of type '(match: `foo${string}`, id: string, index: number, input: `${string}foo${string}${string}`, capturingGroups: [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]) => `foo${string}`' is not assignable to parameter of type 'string | StringReplaceCallbackSignature<[`foo${string}`, string], { id: string; }>'.
!!! error TS2769: Type '(match: `foo${string}`, id: string, index: number, input: `${string}foo${string}${string}`, capturingGroups: [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]) => `foo${string}`' is not assignable to type 'StringReplaceCallbackSignature<[`foo${string}`, string], { id: string; }>'.
!!! error TS2769: Argument of type '(match: `foo${string}`, id: string, index: number, input: `${string}foo${string}`, capturingGroups: [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]) => `foo${string}`' is not assignable to parameter of type 'string | StringReplaceCallbackSignature<[`foo${string}`, string], { id: string; }>'.
!!! error TS2769: Type '(match: `foo${string}`, id: string, index: number, input: `${string}foo${string}`, capturingGroups: [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]) => `foo${string}`' is not assignable to type 'StringReplaceCallbackSignature<[`foo${string}`, string], { id: string; }>'.
!!! error TS2769: Target signature provides too few arguments. Expected 5 or more, but got 4.
!!! related TS6212 regularExpressionTypeCheckingReplace.ts:18:45: Did you mean to call this expression?
!!! related TS2771 lib.es5.d.ts:--:--: The last overload is declared here.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,16 @@ Instantiation count: 10,000
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^
>/foo(\d+)/g : RegExp<[`foo${string}`, string], undefined, { hasIndices: false; global: true; ignoreCase: false; multiline: false; dotAll: false; unicode: false; unicodeSets: false; sticky: false; }>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(match, id, index, input, ...args) => { match; // `foo${string}` id; // string index; // number input; // `${string}foo${string}` args; // [] return match;} : (match: `foo${string}`, id: string, index: number, input: `${string}foo${string}${string}`) => `foo${string}`
> : ^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(match, id, index, input, ...args) => { match; // `foo${string}` id; // string index; // number input; // `${string}foo${string}` args; // [] return match;} : (match: `foo${string}`, id: string, index: number, input: `${string}foo${string}`) => `foo${string}`
> : ^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>match : `foo${string}`
> : ^^^^^^^^^^^^^^
>id : string
> : ^^^^^^
>index : number
> : ^^^^^^
>input : `${string}foo${string}${string}`
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>input : `${string}foo${string}`
> : ^^^^^^^^^^^^^^^^^^^^^^^
>args : []
> : ^^

Expand All @@ -87,8 +87,8 @@ Instantiation count: 10,000
> : ^^^^^^

input; // `${string}foo${string}`
>input : `${string}foo${string}${string}`
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>input : `${string}foo${string}`
> : ^^^^^^^^^^^^^^^^^^^^^^^

args; // []
>args : []
Expand All @@ -111,16 +111,16 @@ Instantiation count: 10,000
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^
>/foo(?<id>\d+)/g : RegExp<[`foo${string}`, string], { id: string; }, { hasIndices: false; global: true; ignoreCase: false; multiline: false; dotAll: false; unicode: false; unicodeSets: false; sticky: false; }>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(match, id, index, input, capturingGroups, ...args) => { match; // `foo${string}` id; // string index; // number input; // `${string}foo${string}` // for target ≥ ES2018 capturingGroups.id; // string capturingGroups.foo; // error args; // [] return match;} : (match: `foo${string}`, id: string, index: number, input: `${string}foo${string}${string}`, capturingGroups: [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]) => `foo${string}`
> : ^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(match, id, index, input, capturingGroups, ...args) => { match; // `foo${string}` id; // string index; // number input; // `${string}foo${string}` // for target ≥ ES2018 capturingGroups.id; // string capturingGroups.foo; // error args; // [] return match;} : (match: `foo${string}`, id: string, index: number, input: `${string}foo${string}`, capturingGroups: [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]) => `foo${string}`
> : ^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>match : `foo${string}`
> : ^^^^^^^^^^^^^^
>id : string
> : ^^^^^^
>index : number
> : ^^^^^^
>input : `${string}foo${string}${string}`
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>input : `${string}foo${string}`
> : ^^^^^^^^^^^^^^^^^^^^^^^
>capturingGroups : [...capturingGroups: CapturingGroups, index: number, input: `${string}${CapturingGroups[0]}${string}`, ...[StringReplaceCallbackOptions, NamedCapturingGroups] extends [StringReplaceCallbackIncludeNamedCapturingGroups, {}] ? [groups: NamedCapturingGroups] : []][4]
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>args : []
Expand All @@ -139,8 +139,8 @@ Instantiation count: 10,000
> : ^^^^^^

input; // `${string}foo${string}`
>input : `${string}foo${string}${string}`
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>input : `${string}foo${string}`
> : ^^^^^^^^^^^^^^^^^^^^^^^

// for target ≥ ES2018
capturingGroups.id; // string
Expand Down
Loading