From a7af92eb630cdd94860ea62867a374eb7e7f2804 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 21 Jun 2018 11:30:37 -0700 Subject: [PATCH] check return tag in getTypePredicateOfSignature (#25130) --- src/compiler/checker.ts | 6 +- .../reference/returnTagTypeGuard.symbols | 63 ++++++++++++++++ .../reference/returnTagTypeGuard.types | 71 +++++++++++++++++++ .../conformance/jsdoc/returnTagTypeGuard.ts | 34 +++++++++ 4 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/returnTagTypeGuard.symbols create mode 100644 tests/baselines/reference/returnTagTypeGuard.types create mode 100644 tests/cases/conformance/jsdoc/returnTagTypeGuard.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3867a26c023..95593dbd380 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7546,9 +7546,9 @@ namespace ts { signature.resolvedTypePredicate = getUnionTypePredicate(signature.unionSignatures) || noTypePredicate; } else { - const declaration = signature.declaration; - signature.resolvedTypePredicate = declaration && declaration.type && declaration.type.kind === SyntaxKind.TypePredicate ? - createTypePredicateFromTypePredicateNode(declaration.type as TypePredicateNode) : + const type = signature.declaration && getEffectiveReturnTypeNode(signature.declaration); + signature.resolvedTypePredicate = type && isTypePredicateNode(type) ? + createTypePredicateFromTypePredicateNode(type) : noTypePredicate; } Debug.assert(!!signature.resolvedTypePredicate); diff --git a/tests/baselines/reference/returnTagTypeGuard.symbols b/tests/baselines/reference/returnTagTypeGuard.symbols new file mode 100644 index 00000000000..c767349c5f2 --- /dev/null +++ b/tests/baselines/reference/returnTagTypeGuard.symbols @@ -0,0 +1,63 @@ +=== tests/cases/conformance/jsdoc/bug25127.js === +class Entry { +>Entry : Symbol(Entry, Decl(bug25127.js, 0, 0)) + + constructor() { + this.c = 1 +>this.c : Symbol(Entry.c, Decl(bug25127.js, 1, 19)) +>this : Symbol(Entry, Decl(bug25127.js, 0, 0)) +>c : Symbol(Entry.c, Decl(bug25127.js, 1, 19)) + } + /** + * @param {any} x + * @return {this is Entry} + */ + isInit(x) { +>isInit : Symbol(Entry.isInit, Decl(bug25127.js, 3, 5)) +>x : Symbol(x, Decl(bug25127.js, 8, 11)) + + return true + } +} +class Group { +>Group : Symbol(Group, Decl(bug25127.js, 11, 1)) + + constructor() { + this.d = 'no' +>this.d : Symbol(Group.d, Decl(bug25127.js, 13, 19)) +>this : Symbol(Group, Decl(bug25127.js, 11, 1)) +>d : Symbol(Group.d, Decl(bug25127.js, 13, 19)) + } + /** + * @param {any} x + * @return {false} + */ + isInit(x) { +>isInit : Symbol(Group.isInit, Decl(bug25127.js, 15, 5)) +>x : Symbol(x, Decl(bug25127.js, 20, 11)) + + return false + } +} +/** @param {Entry | Group} chunk */ +function f(chunk) { +>f : Symbol(f, Decl(bug25127.js, 23, 1)) +>chunk : Symbol(chunk, Decl(bug25127.js, 25, 11)) + + let x = chunk.isInit(chunk) ? chunk.c : chunk.d +>x : Symbol(x, Decl(bug25127.js, 26, 7)) +>chunk.isInit : Symbol(isInit, Decl(bug25127.js, 3, 5), Decl(bug25127.js, 15, 5)) +>chunk : Symbol(chunk, Decl(bug25127.js, 25, 11)) +>isInit : Symbol(isInit, Decl(bug25127.js, 3, 5), Decl(bug25127.js, 15, 5)) +>chunk : Symbol(chunk, Decl(bug25127.js, 25, 11)) +>chunk.c : Symbol(Entry.c, Decl(bug25127.js, 1, 19)) +>chunk : Symbol(chunk, Decl(bug25127.js, 25, 11)) +>c : Symbol(Entry.c, Decl(bug25127.js, 1, 19)) +>chunk.d : Symbol(Group.d, Decl(bug25127.js, 13, 19)) +>chunk : Symbol(chunk, Decl(bug25127.js, 25, 11)) +>d : Symbol(Group.d, Decl(bug25127.js, 13, 19)) + + return x +>x : Symbol(x, Decl(bug25127.js, 26, 7)) +} + diff --git a/tests/baselines/reference/returnTagTypeGuard.types b/tests/baselines/reference/returnTagTypeGuard.types new file mode 100644 index 00000000000..2b59ca44bf1 --- /dev/null +++ b/tests/baselines/reference/returnTagTypeGuard.types @@ -0,0 +1,71 @@ +=== tests/cases/conformance/jsdoc/bug25127.js === +class Entry { +>Entry : Entry + + constructor() { + this.c = 1 +>this.c = 1 : 1 +>this.c : number +>this : this +>c : number +>1 : 1 + } + /** + * @param {any} x + * @return {this is Entry} + */ + isInit(x) { +>isInit : (x: any) => this is Entry +>x : any + + return true +>true : true + } +} +class Group { +>Group : Group + + constructor() { + this.d = 'no' +>this.d = 'no' : "no" +>this.d : string +>this : this +>d : string +>'no' : "no" + } + /** + * @param {any} x + * @return {false} + */ + isInit(x) { +>isInit : (x: any) => false +>x : any + + return false +>false : false + } +} +/** @param {Entry | Group} chunk */ +function f(chunk) { +>f : (chunk: Entry | Group) => string | number +>chunk : Entry | Group + + let x = chunk.isInit(chunk) ? chunk.c : chunk.d +>x : string | number +>chunk.isInit(chunk) ? chunk.c : chunk.d : string | number +>chunk.isInit(chunk) : boolean +>chunk.isInit : ((x: any) => this is Entry) | ((x: any) => false) +>chunk : Entry | Group +>isInit : ((x: any) => this is Entry) | ((x: any) => false) +>chunk : Entry | Group +>chunk.c : number +>chunk : Entry +>c : number +>chunk.d : string +>chunk : Group +>d : string + + return x +>x : string | number +} + diff --git a/tests/cases/conformance/jsdoc/returnTagTypeGuard.ts b/tests/cases/conformance/jsdoc/returnTagTypeGuard.ts new file mode 100644 index 00000000000..8acc3db60a4 --- /dev/null +++ b/tests/cases/conformance/jsdoc/returnTagTypeGuard.ts @@ -0,0 +1,34 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @lib: esnext +// @Filename: bug25127.js +class Entry { + constructor() { + this.c = 1 + } + /** + * @param {any} x + * @return {this is Entry} + */ + isInit(x) { + return true + } +} +class Group { + constructor() { + this.d = 'no' + } + /** + * @param {any} x + * @return {false} + */ + isInit(x) { + return false + } +} +/** @param {Entry | Group} chunk */ +function f(chunk) { + let x = chunk.isInit(chunk) ? chunk.c : chunk.d + return x +}