From 1ecf22884fcad201e8c13c269f2eb531a595dfab Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Mon, 11 Jan 2021 19:25:51 +0200 Subject: [PATCH] fix(42166): allow assertion signature for private identifiers (#42176) --- src/compiler/checker.ts | 11 ++++-- .../reference/privateNamesAssertion.js | 30 ++++++++++++++++ .../reference/privateNamesAssertion.symbols | 31 ++++++++++++++++ .../reference/privateNamesAssertion.types | 36 +++++++++++++++++++ .../privateNames/privateNamesAssertion.ts | 14 ++++++++ 5 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/privateNamesAssertion.js create mode 100644 tests/baselines/reference/privateNamesAssertion.symbols create mode 100644 tests/baselines/reference/privateNamesAssertion.types create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNamesAssertion.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 175518da296..3cc8c60e8d3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21852,10 +21852,15 @@ namespace ts { return getExplicitThisType(node); case SyntaxKind.SuperKeyword: return checkSuperExpression(node); - case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.PropertyAccessExpression: { const type = getTypeOfDottedName((node).expression, diagnostic); - const prop = type && getPropertyOfType(type, (node).name.escapedText); - return prop && getExplicitTypeOfSymbol(prop, diagnostic); + if (type) { + const name = (node).name; + const prop = getPropertyOfType(type, isPrivateIdentifier(name) ? getSymbolNameForPrivateIdentifier(type.symbol, name.escapedText) : name.escapedText); + return prop && getExplicitTypeOfSymbol(prop, diagnostic); + } + return undefined; + } case SyntaxKind.ParenthesizedExpression: return getTypeOfDottedName((node).expression, diagnostic); } diff --git a/tests/baselines/reference/privateNamesAssertion.js b/tests/baselines/reference/privateNamesAssertion.js new file mode 100644 index 00000000000..66af365350b --- /dev/null +++ b/tests/baselines/reference/privateNamesAssertion.js @@ -0,0 +1,30 @@ +//// [privateNamesAssertion.ts] +class Foo { + #p1: (v: any) => asserts v is string = (v) => { + if (typeof v !== "string") { + throw new Error(); + } + } + m1(v: unknown) { + this.#p1(v); + v; + } +} + + +//// [privateNamesAssertion.js] +"use strict"; +class Foo { + constructor() { + this.#p1 = (v) => { + if (typeof v !== "string") { + throw new Error(); + } + }; + } + #p1; + m1(v) { + this.#p1(v); + v; + } +} diff --git a/tests/baselines/reference/privateNamesAssertion.symbols b/tests/baselines/reference/privateNamesAssertion.symbols new file mode 100644 index 00000000000..40d903912e7 --- /dev/null +++ b/tests/baselines/reference/privateNamesAssertion.symbols @@ -0,0 +1,31 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAssertion.ts === +class Foo { +>Foo : Symbol(Foo, Decl(privateNamesAssertion.ts, 0, 0)) + + #p1: (v: any) => asserts v is string = (v) => { +>#p1 : Symbol(Foo.#p1, Decl(privateNamesAssertion.ts, 0, 11)) +>v : Symbol(v, Decl(privateNamesAssertion.ts, 1, 10)) +>v : Symbol(v, Decl(privateNamesAssertion.ts, 1, 10)) +>v : Symbol(v, Decl(privateNamesAssertion.ts, 1, 44)) + + if (typeof v !== "string") { +>v : Symbol(v, Decl(privateNamesAssertion.ts, 1, 44)) + + throw new Error(); +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + } + } + m1(v: unknown) { +>m1 : Symbol(Foo.m1, Decl(privateNamesAssertion.ts, 5, 5)) +>v : Symbol(v, Decl(privateNamesAssertion.ts, 6, 7)) + + this.#p1(v); +>this.#p1 : Symbol(Foo.#p1, Decl(privateNamesAssertion.ts, 0, 11)) +>this : Symbol(Foo, Decl(privateNamesAssertion.ts, 0, 0)) +>v : Symbol(v, Decl(privateNamesAssertion.ts, 6, 7)) + + v; +>v : Symbol(v, Decl(privateNamesAssertion.ts, 6, 7)) + } +} + diff --git a/tests/baselines/reference/privateNamesAssertion.types b/tests/baselines/reference/privateNamesAssertion.types new file mode 100644 index 00000000000..ff0dd98d402 --- /dev/null +++ b/tests/baselines/reference/privateNamesAssertion.types @@ -0,0 +1,36 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNamesAssertion.ts === +class Foo { +>Foo : Foo + + #p1: (v: any) => asserts v is string = (v) => { +>#p1 : (v: any) => asserts v is string +>v : any +>(v) => { if (typeof v !== "string") { throw new Error(); } } : (v: any) => void +>v : any + + if (typeof v !== "string") { +>typeof v !== "string" : boolean +>typeof v : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>v : any +>"string" : "string" + + throw new Error(); +>new Error() : Error +>Error : ErrorConstructor + } + } + m1(v: unknown) { +>m1 : (v: unknown) => void +>v : unknown + + this.#p1(v); +>this.#p1(v) : void +>this.#p1 : (v: any) => asserts v is string +>this : this +>v : unknown + + v; +>v : string + } +} + diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAssertion.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAssertion.ts new file mode 100644 index 00000000000..69d552b6f0b --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAssertion.ts @@ -0,0 +1,14 @@ +// @strict: true +// @target: esnext + +class Foo { + #p1: (v: any) => asserts v is string = (v) => { + if (typeof v !== "string") { + throw new Error(); + } + } + m1(v: unknown) { + this.#p1(v); + v; + } +}