Skip to content

Commit 9be0f1b

Browse files
authored
Merge pull request microsoft#17708 from Microsoft/fix-type-predicate-index-in-errors
Fix type predicate index in error reporting
2 parents e1ba65a + a59f77f commit 9be0f1b

5 files changed

Lines changed: 61 additions & 6 deletions

File tree

src/compiler/checker.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8592,7 +8592,7 @@ namespace ts {
85928592
// The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions
85938593
if (target.typePredicate) {
85948594
if (source.typePredicate) {
8595-
result &= compareTypePredicateRelatedTo(source.typePredicate, target.typePredicate, reportErrors, errorReporter, compareTypes);
8595+
result &= compareTypePredicateRelatedTo(source.typePredicate, target.typePredicate, source.declaration, target.declaration, reportErrors, errorReporter, compareTypes);
85968596
}
85978597
else if (isIdentifierTypePredicate(target.typePredicate)) {
85988598
if (reportErrors) {
@@ -8614,8 +8614,11 @@ namespace ts {
86148614
return result;
86158615
}
86168616

8617-
function compareTypePredicateRelatedTo(source: TypePredicate,
8617+
function compareTypePredicateRelatedTo(
8618+
source: TypePredicate,
86188619
target: TypePredicate,
8620+
sourceDeclaration: SignatureDeclaration,
8621+
targetDeclaration: SignatureDeclaration,
86198622
reportErrors: boolean,
86208623
errorReporter: ErrorReporter,
86218624
compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary {
@@ -8628,11 +8631,13 @@ namespace ts {
86288631
}
86298632

86308633
if (source.kind === TypePredicateKind.Identifier) {
8631-
const sourceIdentifierPredicate = source as IdentifierTypePredicate;
8632-
const targetIdentifierPredicate = target as IdentifierTypePredicate;
8633-
if (sourceIdentifierPredicate.parameterIndex !== targetIdentifierPredicate.parameterIndex) {
8634+
const sourcePredicate = source as IdentifierTypePredicate;
8635+
const targetPredicate = target as IdentifierTypePredicate;
8636+
const sourceIndex = sourcePredicate.parameterIndex - (getThisParameter(sourceDeclaration) ? 1 : 0);
8637+
const targetIndex = targetPredicate.parameterIndex - (getThisParameter(targetDeclaration) ? 1 : 0);
8638+
if (sourceIndex !== targetIndex) {
86348639
if (reportErrors) {
8635-
errorReporter(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, sourceIdentifierPredicate.parameterName, targetIdentifierPredicate.parameterName);
8640+
errorReporter(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, sourcePredicate.parameterName, targetPredicate.parameterName);
86368641
errorReporter(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target));
86378642
}
86388643
return Ternary.False;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//// [thisTypeInTypePredicate.ts]
2+
declare function filter<S>(f: (this: void, x: any) => x is S): S[];
3+
const numbers = filter<number>((x): x is number => 'number' == typeof x)
4+
5+
6+
//// [thisTypeInTypePredicate.js]
7+
var numbers = filter(function (x) { return 'number' == typeof x; });
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
=== tests/cases/conformance/types/thisType/thisTypeInTypePredicate.ts ===
2+
declare function filter<S>(f: (this: void, x: any) => x is S): S[];
3+
>filter : Symbol(filter, Decl(thisTypeInTypePredicate.ts, 0, 0))
4+
>S : Symbol(S, Decl(thisTypeInTypePredicate.ts, 0, 24))
5+
>f : Symbol(f, Decl(thisTypeInTypePredicate.ts, 0, 27))
6+
>this : Symbol(this, Decl(thisTypeInTypePredicate.ts, 0, 31))
7+
>x : Symbol(x, Decl(thisTypeInTypePredicate.ts, 0, 42))
8+
>x : Symbol(x, Decl(thisTypeInTypePredicate.ts, 0, 42))
9+
>S : Symbol(S, Decl(thisTypeInTypePredicate.ts, 0, 24))
10+
>S : Symbol(S, Decl(thisTypeInTypePredicate.ts, 0, 24))
11+
12+
const numbers = filter<number>((x): x is number => 'number' == typeof x)
13+
>numbers : Symbol(numbers, Decl(thisTypeInTypePredicate.ts, 1, 5))
14+
>filter : Symbol(filter, Decl(thisTypeInTypePredicate.ts, 0, 0))
15+
>x : Symbol(x, Decl(thisTypeInTypePredicate.ts, 1, 32))
16+
>x : Symbol(x, Decl(thisTypeInTypePredicate.ts, 1, 32))
17+
>x : Symbol(x, Decl(thisTypeInTypePredicate.ts, 1, 32))
18+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
=== tests/cases/conformance/types/thisType/thisTypeInTypePredicate.ts ===
2+
declare function filter<S>(f: (this: void, x: any) => x is S): S[];
3+
>filter : <S>(f: (this: void, x: any) => x is S) => S[]
4+
>S : S
5+
>f : (this: void, x: any) => x is S
6+
>this : void
7+
>x : any
8+
>x : any
9+
>S : S
10+
>S : S
11+
12+
const numbers = filter<number>((x): x is number => 'number' == typeof x)
13+
>numbers : number[]
14+
>filter<number>((x): x is number => 'number' == typeof x) : number[]
15+
>filter : <S>(f: (this: void, x: any) => x is S) => S[]
16+
>(x): x is number => 'number' == typeof x : (this: void, x: any) => x is number
17+
>x : any
18+
>x : any
19+
>'number' == typeof x : boolean
20+
>'number' : "number"
21+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
22+
>x : any
23+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
declare function filter<S>(f: (this: void, x: any) => x is S): S[];
2+
const numbers = filter<number>((x): x is number => 'number' == typeof x)

0 commit comments

Comments
 (0)