Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 18 additions & 12 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5103,17 +5103,6 @@ namespace ts {
}
return Ternary.False;
}
if (sourcePredicate.predicate.kind === TypePredicateKind.Identifier) {
const sourceIdentifierPredicate = sourcePredicate.predicate as IdentifierTypePredicate;
const targetIdentifierPredicate = targetPredicate.predicate as IdentifierTypePredicate;
if (sourceIdentifierPredicate.parameterIndex !== targetIdentifierPredicate.parameterIndex) {
if (reportErrors) {
reportError(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, sourceIdentifierPredicate.parameterName, targetIdentifierPredicate.parameterName);
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typeToString(source), typeToString(target));
}
return Ternary.False;
}
}
const related = isRelatedTo(sourcePredicate.predicate.type, targetPredicate.predicate.type, reportErrors, headMessage);
if (related === Ternary.False && reportErrors) {
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typeToString(source), typeToString(target));
Expand Down Expand Up @@ -5666,7 +5655,24 @@ namespace ts {
}
}

return result & isRelatedTo(sourceReturnType, targetReturnType, reportErrors);
result = result & isRelatedTo(sourceReturnType, targetReturnType, reportErrors);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be a better idea to first check if they are both predicate types, since it doesn't look like you need to relate the return types in that case.

if (!(sourceReturnType.flags & TypeFlags.PredicateType && targetReturnType.flags & TypeFlags.PredicateType)) {
return result;
}
const sourcePredicate = sourceReturnType as PredicateType;
const targetPredicate = targetReturnType as PredicateType;
if (sourcePredicate.predicate.kind === TypePredicateKind.Identifier) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't they both need to have the same predicate type?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

const sourceIdentifierPredicate = sourcePredicate.predicate as IdentifierTypePredicate;
const targetIdentifierPredicate = targetPredicate.predicate as IdentifierTypePredicate;
if (sourceIdentifierPredicate.parameterIndex !== targetIdentifierPredicate.parameterIndex) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the parameterIndex and the predicate kind need to be on the type predicate anymore? Can they just be on the signature?

if (reportErrors) {
reportError(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, sourceIdentifierPredicate.parameterName, targetIdentifierPredicate.parameterName);
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typeToString(sourceReturnType), typeToString(targetReturnType));
}
return Ternary.False;
}
}
return result;
}

function signaturesIdenticalTo(source: Type, target: Type, kind: SignatureKind): Ternary {
Expand Down
26 changes: 26 additions & 0 deletions tests/baselines/reference/typeGuardOfFormFunctionEquality.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//// [typeGuardOfFormFunctionEquality.ts]
declare function isString1(a: number, b: Object): b is string;

declare function isString2(a: Object): a is string;

switch (isString1(0, "")) {
case isString2(""):
default:
}

var x = isString1(0, "") === isString2("");

function isString3(a: number, b: number, c: Object): c is string {
return isString1(0, c);
}


//// [typeGuardOfFormFunctionEquality.js]
switch (isString1(0, "")) {
case isString2(""):
default:
}
var x = isString1(0, "") === isString2("");
function isString3(a, b, c) {
return isString1(0, c);
}
41 changes: 41 additions & 0 deletions tests/baselines/reference/typeGuardOfFormFunctionEquality.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormFunctionEquality.ts ===
declare function isString1(a: number, b: Object): b is string;
>isString1 : Symbol(isString1, Decl(typeGuardOfFormFunctionEquality.ts, 0, 0))
>a : Symbol(a, Decl(typeGuardOfFormFunctionEquality.ts, 0, 27))
>b : Symbol(b, Decl(typeGuardOfFormFunctionEquality.ts, 0, 37))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>b : Symbol(b, Decl(typeGuardOfFormFunctionEquality.ts, 0, 37))

declare function isString2(a: Object): a is string;
>isString2 : Symbol(isString2, Decl(typeGuardOfFormFunctionEquality.ts, 0, 62))
>a : Symbol(a, Decl(typeGuardOfFormFunctionEquality.ts, 2, 27))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>a : Symbol(a, Decl(typeGuardOfFormFunctionEquality.ts, 2, 27))

switch (isString1(0, "")) {
>isString1 : Symbol(isString1, Decl(typeGuardOfFormFunctionEquality.ts, 0, 0))

case isString2(""):
>isString2 : Symbol(isString2, Decl(typeGuardOfFormFunctionEquality.ts, 0, 62))

default:
}

var x = isString1(0, "") === isString2("");
>x : Symbol(x, Decl(typeGuardOfFormFunctionEquality.ts, 9, 3))
>isString1 : Symbol(isString1, Decl(typeGuardOfFormFunctionEquality.ts, 0, 0))
>isString2 : Symbol(isString2, Decl(typeGuardOfFormFunctionEquality.ts, 0, 62))

function isString3(a: number, b: number, c: Object): c is string {
>isString3 : Symbol(isString3, Decl(typeGuardOfFormFunctionEquality.ts, 9, 43))
>a : Symbol(a, Decl(typeGuardOfFormFunctionEquality.ts, 11, 19))
>b : Symbol(b, Decl(typeGuardOfFormFunctionEquality.ts, 11, 29))
>c : Symbol(c, Decl(typeGuardOfFormFunctionEquality.ts, 11, 40))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>c : Symbol(c, Decl(typeGuardOfFormFunctionEquality.ts, 11, 40))

return isString1(0, c);
>isString1 : Symbol(isString1, Decl(typeGuardOfFormFunctionEquality.ts, 0, 0))
>c : Symbol(c, Decl(typeGuardOfFormFunctionEquality.ts, 11, 40))
}

54 changes: 54 additions & 0 deletions tests/baselines/reference/typeGuardOfFormFunctionEquality.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormFunctionEquality.ts ===
declare function isString1(a: number, b: Object): b is string;
>isString1 : (a: number, b: Object) => b is string
>a : number
>b : Object
>Object : Object
>b : any

declare function isString2(a: Object): a is string;
>isString2 : (a: Object) => a is string
>a : Object
>Object : Object
>a : any

switch (isString1(0, "")) {
>isString1(0, "") : b is string
>isString1 : (a: number, b: Object) => b is string
>0 : number
>"" : string

case isString2(""):
>isString2("") : a is string
>isString2 : (a: Object) => a is string
>"" : string

default:
}

var x = isString1(0, "") === isString2("");
>x : boolean
>isString1(0, "") === isString2("") : boolean
>isString1(0, "") : b is string
>isString1 : (a: number, b: Object) => b is string
>0 : number
>"" : string
>isString2("") : a is string
>isString2 : (a: Object) => a is string
>"" : string

function isString3(a: number, b: number, c: Object): c is string {
>isString3 : (a: number, b: number, c: Object) => c is string
>a : number
>b : number
>c : Object
>Object : Object
>c : any

return isString1(0, c);
>isString1(0, c) : b is string
>isString1 : (a: number, b: Object) => b is string
>0 : number
>c : Object
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
declare function isString1(a: number, b: Object): b is string;

declare function isString2(a: Object): a is string;

switch (isString1(0, "")) {
case isString2(""):
default:
}

var x = isString1(0, "") === isString2("");

function isString3(a: number, b: number, c: Object): c is string {
return isString1(0, c);
}