mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-11 16:38:46 -05:00
Support prototype assignment with a function declaration (#25300)
Previously variable declaration+function expression worked. Note that class expression/class declaration do not work, due to the way they are specified. I added a test for future reference.
This commit is contained in:
committed by
GitHub
parent
1579bfdd46
commit
50ef631b59
@@ -19458,7 +19458,8 @@ namespace ts {
|
||||
function getAssignedClassType(symbol: Symbol) {
|
||||
const decl = symbol.valueDeclaration;
|
||||
const assignmentSymbol = decl && decl.parent &&
|
||||
(isBinaryExpression(decl.parent) && getSymbolOfNode(decl.parent.left) ||
|
||||
(isFunctionDeclaration(decl) && getSymbolOfNode(decl) ||
|
||||
isBinaryExpression(decl.parent) && getSymbolOfNode(decl.parent.left) ||
|
||||
isVariableDeclaration(decl.parent) && getSymbolOfNode(decl.parent));
|
||||
if (assignmentSymbol) {
|
||||
const prototype = forEach(assignmentSymbol.declarations, getAssignedJavascriptPrototype);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
// mixed prototype-assignment+function declaration
|
||||
function C() { this.p = 1; }
|
||||
>C : Symbol(C, Decl(a.js, 0, 0), Decl(a.js, 1, 28))
|
||||
>p : Symbol(C.p, Decl(a.js, 1, 14))
|
||||
|
||||
C.prototype = { q: 2 };
|
||||
>C.prototype : Symbol(C.prototype, Decl(a.js, 1, 28))
|
||||
>C : Symbol(C, Decl(a.js, 0, 0), Decl(a.js, 1, 28))
|
||||
>prototype : Symbol(C.prototype, Decl(a.js, 1, 28))
|
||||
>q : Symbol(q, Decl(a.js, 2, 15))
|
||||
|
||||
const c = new C()
|
||||
>c : Symbol(c, Decl(a.js, 4, 5))
|
||||
>C : Symbol(C, Decl(a.js, 0, 0), Decl(a.js, 1, 28))
|
||||
|
||||
c.p
|
||||
>c.p : Symbol(C.p, Decl(a.js, 1, 14))
|
||||
>c : Symbol(c, Decl(a.js, 4, 5))
|
||||
>p : Symbol(C.p, Decl(a.js, 1, 14))
|
||||
|
||||
c.q
|
||||
>c.q : Symbol(q, Decl(a.js, 2, 15))
|
||||
>c : Symbol(c, Decl(a.js, 4, 5))
|
||||
>q : Symbol(q, Decl(a.js, 2, 15))
|
||||
|
||||
34
tests/baselines/reference/typeFromPropertyAssignment27.types
Normal file
34
tests/baselines/reference/typeFromPropertyAssignment27.types
Normal file
@@ -0,0 +1,34 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
// mixed prototype-assignment+function declaration
|
||||
function C() { this.p = 1; }
|
||||
>C : typeof C
|
||||
>this.p = 1 : 1
|
||||
>this.p : any
|
||||
>this : any
|
||||
>p : any
|
||||
>1 : 1
|
||||
|
||||
C.prototype = { q: 2 };
|
||||
>C.prototype = { q: 2 } : { [x: string]: any; q: number; }
|
||||
>C.prototype : { [x: string]: any; }
|
||||
>C : typeof C
|
||||
>prototype : { [x: string]: any; }
|
||||
>{ q: 2 } : { [x: string]: any; q: number; }
|
||||
>q : number
|
||||
>2 : 2
|
||||
|
||||
const c = new C()
|
||||
>c : C & { [x: string]: any; q: number; }
|
||||
>new C() : C & { [x: string]: any; q: number; }
|
||||
>C : typeof C
|
||||
|
||||
c.p
|
||||
>c.p : number
|
||||
>c : C & { [x: string]: any; q: number; }
|
||||
>p : number
|
||||
|
||||
c.q
|
||||
>c.q : number
|
||||
>c : C & { [x: string]: any; q: number; }
|
||||
>q : number
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
tests/cases/conformance/salsa/a.js(7,17): error TS2322: Type '{ [x: string]: any; q: number; }' is not assignable to type 'C'.
|
||||
Object literal may only specify known properties, and 'q' does not exist in type 'C'.
|
||||
tests/cases/conformance/salsa/a.js(11,3): error TS2339: Property 'q' does not exist on type 'C'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/salsa/a.js (2 errors) ====
|
||||
// mixed prototype-assignment+class declaration
|
||||
class C { constructor() { this.p = 1; } }
|
||||
// Property assignment does nothing.
|
||||
// You have to use Object.defineProperty(C, "prototype", { q: 2 })
|
||||
// and that only works on classes with no superclass.
|
||||
// (Object.defineProperty isn't recognised as a JS special assignment right now.)
|
||||
C.prototype = { q: 2 };
|
||||
~~~~
|
||||
!!! error TS2322: Type '{ [x: string]: any; q: number; }' is not assignable to type 'C'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'q' does not exist in type 'C'.
|
||||
|
||||
const c = new C()
|
||||
c.p
|
||||
c.q
|
||||
~
|
||||
!!! error TS2339: Property 'q' does not exist on type 'C'.
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
// mixed prototype-assignment+class declaration
|
||||
class C { constructor() { this.p = 1; } }
|
||||
>C : Symbol(C, Decl(a.js, 0, 0), Decl(a.js, 1, 41))
|
||||
>this.p : Symbol(C.p, Decl(a.js, 1, 25))
|
||||
>this : Symbol(C, Decl(a.js, 0, 0), Decl(a.js, 1, 41))
|
||||
>p : Symbol(C.p, Decl(a.js, 1, 25))
|
||||
|
||||
// Property assignment does nothing.
|
||||
// You have to use Object.defineProperty(C, "prototype", { q: 2 })
|
||||
// and that only works on classes with no superclass.
|
||||
// (Object.defineProperty isn't recognised as a JS special assignment right now.)
|
||||
C.prototype = { q: 2 };
|
||||
>C.prototype : Symbol(C.prototype, Decl(a.js, 1, 41))
|
||||
>C : Symbol(C, Decl(a.js, 0, 0), Decl(a.js, 1, 41))
|
||||
>prototype : Symbol(C.prototype, Decl(a.js, 1, 41))
|
||||
>q : Symbol(q, Decl(a.js, 6, 15))
|
||||
|
||||
const c = new C()
|
||||
>c : Symbol(c, Decl(a.js, 8, 5))
|
||||
>C : Symbol(C, Decl(a.js, 0, 0), Decl(a.js, 1, 41))
|
||||
|
||||
c.p
|
||||
>c.p : Symbol(C.p, Decl(a.js, 1, 25))
|
||||
>c : Symbol(c, Decl(a.js, 8, 5))
|
||||
>p : Symbol(C.p, Decl(a.js, 1, 25))
|
||||
|
||||
c.q
|
||||
>c : Symbol(c, Decl(a.js, 8, 5))
|
||||
|
||||
38
tests/baselines/reference/typeFromPropertyAssignment28.types
Normal file
38
tests/baselines/reference/typeFromPropertyAssignment28.types
Normal file
@@ -0,0 +1,38 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
// mixed prototype-assignment+class declaration
|
||||
class C { constructor() { this.p = 1; } }
|
||||
>C : C
|
||||
>this.p = 1 : 1
|
||||
>this.p : number
|
||||
>this : this
|
||||
>p : number
|
||||
>1 : 1
|
||||
|
||||
// Property assignment does nothing.
|
||||
// You have to use Object.defineProperty(C, "prototype", { q: 2 })
|
||||
// and that only works on classes with no superclass.
|
||||
// (Object.defineProperty isn't recognised as a JS special assignment right now.)
|
||||
C.prototype = { q: 2 };
|
||||
>C.prototype = { q: 2 } : { [x: string]: any; q: number; }
|
||||
>C.prototype : C
|
||||
>C : typeof C
|
||||
>prototype : C
|
||||
>{ q: 2 } : { [x: string]: any; q: number; }
|
||||
>q : number
|
||||
>2 : 2
|
||||
|
||||
const c = new C()
|
||||
>c : C
|
||||
>new C() : C
|
||||
>C : typeof C
|
||||
|
||||
c.p
|
||||
>c.p : number
|
||||
>c : C
|
||||
>p : number
|
||||
|
||||
c.q
|
||||
>c.q : any
|
||||
>c : C
|
||||
>q : any
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// @noEmit: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @Filename: a.js
|
||||
// mixed prototype-assignment+function declaration
|
||||
function C() { this.p = 1; }
|
||||
C.prototype = { q: 2 };
|
||||
|
||||
const c = new C()
|
||||
c.p
|
||||
c.q
|
||||
@@ -0,0 +1,15 @@
|
||||
// @noEmit: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @Filename: a.js
|
||||
// mixed prototype-assignment+class declaration
|
||||
class C { constructor() { this.p = 1; } }
|
||||
// Property assignment does nothing.
|
||||
// You have to use Object.defineProperty(C, "prototype", { q: 2 })
|
||||
// and that only works on classes with no superclass.
|
||||
// (Object.defineProperty isn't recognised as a JS special assignment right now.)
|
||||
C.prototype = { q: 2 };
|
||||
|
||||
const c = new C()
|
||||
c.p
|
||||
c.q
|
||||
Reference in New Issue
Block a user