Skip to content

Commit 6173696

Browse files
committed
Merge pull request microsoft#8825 from Microsoft/Fix8795-1
Fix microsoft#8795: make properties defined in optional constructor parameters optional
2 parents df4ab08 + 6ab3891 commit 6173696

10 files changed

+186
-45
lines changed

src/compiler/binder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2027,7 +2027,7 @@ namespace ts {
20272027
// containing class.
20282028
if (isParameterPropertyDeclaration(node)) {
20292029
const classDeclaration = <ClassLikeDeclaration>node.parent.parent;
2030-
declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
2030+
declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
20312031
}
20322032
}
20332033

tests/baselines/reference/assignmentCompatability10.errors.txt

Lines changed: 0 additions & 17 deletions
This file was deleted.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
=== tests/cases/compiler/assignmentCompatability10.ts ===
2+
module __test1__ {
3+
>__test1__ : Symbol(__test1__, Decl(assignmentCompatability10.ts, 0, 0))
4+
5+
export interface interfaceWithPublicAndOptional<T,U> { one: T; two?: U; }; var obj4: interfaceWithPublicAndOptional<number,string> = { one: 1 };;
6+
>interfaceWithPublicAndOptional : Symbol(interfaceWithPublicAndOptional, Decl(assignmentCompatability10.ts, 0, 18))
7+
>T : Symbol(T, Decl(assignmentCompatability10.ts, 1, 52))
8+
>U : Symbol(U, Decl(assignmentCompatability10.ts, 1, 54))
9+
>one : Symbol(interfaceWithPublicAndOptional.one, Decl(assignmentCompatability10.ts, 1, 58))
10+
>T : Symbol(T, Decl(assignmentCompatability10.ts, 1, 52))
11+
>two : Symbol(interfaceWithPublicAndOptional.two, Decl(assignmentCompatability10.ts, 1, 66))
12+
>U : Symbol(U, Decl(assignmentCompatability10.ts, 1, 54))
13+
>obj4 : Symbol(obj4, Decl(assignmentCompatability10.ts, 1, 83))
14+
>interfaceWithPublicAndOptional : Symbol(interfaceWithPublicAndOptional, Decl(assignmentCompatability10.ts, 0, 18))
15+
>one : Symbol(one, Decl(assignmentCompatability10.ts, 1, 139))
16+
17+
export var __val__obj4 = obj4;
18+
>__val__obj4 : Symbol(__val__obj4, Decl(assignmentCompatability10.ts, 2, 14))
19+
>obj4 : Symbol(obj4, Decl(assignmentCompatability10.ts, 1, 83))
20+
}
21+
module __test2__ {
22+
>__test2__ : Symbol(__test2__, Decl(assignmentCompatability10.ts, 3, 1))
23+
24+
export class classWithPublicAndOptional<T,U> { constructor(public one: T, public two?: U) {} } var x4 = new classWithPublicAndOptional<number, string>(1);;
25+
>classWithPublicAndOptional : Symbol(classWithPublicAndOptional, Decl(assignmentCompatability10.ts, 4, 18))
26+
>T : Symbol(T, Decl(assignmentCompatability10.ts, 5, 44))
27+
>U : Symbol(U, Decl(assignmentCompatability10.ts, 5, 46))
28+
>one : Symbol(classWithPublicAndOptional.one, Decl(assignmentCompatability10.ts, 5, 63))
29+
>T : Symbol(T, Decl(assignmentCompatability10.ts, 5, 44))
30+
>two : Symbol(classWithPublicAndOptional.two, Decl(assignmentCompatability10.ts, 5, 77))
31+
>U : Symbol(U, Decl(assignmentCompatability10.ts, 5, 46))
32+
>x4 : Symbol(x4, Decl(assignmentCompatability10.ts, 5, 104))
33+
>classWithPublicAndOptional : Symbol(classWithPublicAndOptional, Decl(assignmentCompatability10.ts, 4, 18))
34+
35+
export var __val__x4 = x4;
36+
>__val__x4 : Symbol(__val__x4, Decl(assignmentCompatability10.ts, 6, 14))
37+
>x4 : Symbol(x4, Decl(assignmentCompatability10.ts, 5, 104))
38+
}
39+
__test2__.__val__x4 = __test1__.__val__obj4
40+
>__test2__.__val__x4 : Symbol(__test2__.__val__x4, Decl(assignmentCompatability10.ts, 6, 14))
41+
>__test2__ : Symbol(__test2__, Decl(assignmentCompatability10.ts, 3, 1))
42+
>__val__x4 : Symbol(__test2__.__val__x4, Decl(assignmentCompatability10.ts, 6, 14))
43+
>__test1__.__val__obj4 : Symbol(__test1__.__val__obj4, Decl(assignmentCompatability10.ts, 2, 14))
44+
>__test1__ : Symbol(__test1__, Decl(assignmentCompatability10.ts, 0, 0))
45+
>__val__obj4 : Symbol(__test1__.__val__obj4, Decl(assignmentCompatability10.ts, 2, 14))
46+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
=== tests/cases/compiler/assignmentCompatability10.ts ===
2+
module __test1__ {
3+
>__test1__ : typeof __test1__
4+
5+
export interface interfaceWithPublicAndOptional<T,U> { one: T; two?: U; }; var obj4: interfaceWithPublicAndOptional<number,string> = { one: 1 };;
6+
>interfaceWithPublicAndOptional : interfaceWithPublicAndOptional<T, U>
7+
>T : T
8+
>U : U
9+
>one : T
10+
>T : T
11+
>two : U
12+
>U : U
13+
>obj4 : interfaceWithPublicAndOptional<number, string>
14+
>interfaceWithPublicAndOptional : interfaceWithPublicAndOptional<T, U>
15+
>{ one: 1 } : { one: number; }
16+
>one : number
17+
>1 : number
18+
19+
export var __val__obj4 = obj4;
20+
>__val__obj4 : interfaceWithPublicAndOptional<number, string>
21+
>obj4 : interfaceWithPublicAndOptional<number, string>
22+
}
23+
module __test2__ {
24+
>__test2__ : typeof __test2__
25+
26+
export class classWithPublicAndOptional<T,U> { constructor(public one: T, public two?: U) {} } var x4 = new classWithPublicAndOptional<number, string>(1);;
27+
>classWithPublicAndOptional : classWithPublicAndOptional<T, U>
28+
>T : T
29+
>U : U
30+
>one : T
31+
>T : T
32+
>two : U
33+
>U : U
34+
>x4 : classWithPublicAndOptional<number, string>
35+
>new classWithPublicAndOptional<number, string>(1) : classWithPublicAndOptional<number, string>
36+
>classWithPublicAndOptional : typeof classWithPublicAndOptional
37+
>1 : number
38+
39+
export var __val__x4 = x4;
40+
>__val__x4 : classWithPublicAndOptional<number, string>
41+
>x4 : classWithPublicAndOptional<number, string>
42+
}
43+
__test2__.__val__x4 = __test1__.__val__obj4
44+
>__test2__.__val__x4 = __test1__.__val__obj4 : __test1__.interfaceWithPublicAndOptional<number, string>
45+
>__test2__.__val__x4 : __test2__.classWithPublicAndOptional<number, string>
46+
>__test2__ : typeof __test2__
47+
>__val__x4 : __test2__.classWithPublicAndOptional<number, string>
48+
>__test1__.__val__obj4 : __test1__.interfaceWithPublicAndOptional<number, string>
49+
>__test1__ : typeof __test1__
50+
>__val__obj4 : __test1__.interfaceWithPublicAndOptional<number, string>
51+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
tests/cases/compiler/optionalParameterProperty.ts(6,7): error TS2415: Class 'D' incorrectly extends base class 'C'.
2+
Types of property 'p' are incompatible.
3+
Type 'number | undefined' is not assignable to type 'number'.
4+
Type 'undefined' is not assignable to type 'number'.
5+
6+
7+
==== tests/cases/compiler/optionalParameterProperty.ts (1 errors) ====
8+
9+
class C {
10+
p: number;
11+
}
12+
13+
class D extends C {
14+
~
15+
!!! error TS2415: Class 'D' incorrectly extends base class 'C'.
16+
!!! error TS2415: Types of property 'p' are incompatible.
17+
!!! error TS2415: Type 'number | undefined' is not assignable to type 'number'.
18+
!!! error TS2415: Type 'undefined' is not assignable to type 'number'.
19+
constructor(public p?: number) {
20+
super();
21+
}
22+
}
23+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//// [optionalParameterProperty.ts]
2+
3+
class C {
4+
p: number;
5+
}
6+
7+
class D extends C {
8+
constructor(public p?: number) {
9+
super();
10+
}
11+
}
12+
13+
14+
//// [optionalParameterProperty.js]
15+
var __extends = (this && this.__extends) || function (d, b) {
16+
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
17+
function __() { this.constructor = d; }
18+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
19+
};
20+
var C = (function () {
21+
function C() {
22+
}
23+
return C;
24+
}());
25+
var D = (function (_super) {
26+
__extends(D, _super);
27+
function D(p) {
28+
_super.call(this);
29+
this.p = p;
30+
}
31+
return D;
32+
}(C));
Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
1-
tests/cases/compiler/propertyParameterWithQuestionMark.ts(6,5): error TS2322: Type '{}' is not assignable to type 'C'.
2-
Property 'x' is missing in type '{}'.
3-
tests/cases/compiler/propertyParameterWithQuestionMark.ts(8,1): error TS2322: Type '{ x?: any; }' is not assignable to type 'C'.
4-
Property 'x' is optional in type '{ x?: any; }' but required in type 'C'.
1+
tests/cases/compiler/propertyParameterWithQuestionMark.ts(9,5): error TS2322: Type 'C' is not assignable to type '{ x: any; }'.
2+
Property 'x' is optional in type 'C' but required in type '{ x: any; }'.
53

64

7-
==== tests/cases/compiler/propertyParameterWithQuestionMark.ts (2 errors) ====
5+
==== tests/cases/compiler/propertyParameterWithQuestionMark.ts (1 errors) ====
86
class C {
97
constructor(public x?) { }
108
}
119

12-
// x should not be an optional property
13-
var v: C = {}; // Should fail
14-
~
15-
!!! error TS2322: Type '{}' is not assignable to type 'C'.
16-
!!! error TS2322: Property 'x' is missing in type '{}'.
10+
// x should be an optional property
11+
var v: C = {}; // Should succeed
1712
var v2: { x? }
18-
v = v2; // Should fail
19-
~
20-
!!! error TS2322: Type '{ x?: any; }' is not assignable to type 'C'.
21-
!!! error TS2322: Property 'x' is optional in type '{ x?: any; }' but required in type 'C'.
22-
var v3: { x } = new C; // Should succeed
13+
v = v2; // Should succeed
14+
var v3: { x } = new C; // Should fail
15+
~~
16+
!!! error TS2322: Type 'C' is not assignable to type '{ x: any; }'.
17+
!!! error TS2322: Property 'x' is optional in type 'C' but required in type '{ x: any; }'.

tests/baselines/reference/propertyParameterWithQuestionMark.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ class C {
33
constructor(public x?) { }
44
}
55

6-
// x should not be an optional property
7-
var v: C = {}; // Should fail
6+
// x should be an optional property
7+
var v: C = {}; // Should succeed
88
var v2: { x? }
9-
v = v2; // Should fail
10-
var v3: { x } = new C; // Should succeed
9+
v = v2; // Should succeed
10+
var v3: { x } = new C; // Should fail
1111

1212
//// [propertyParameterWithQuestionMark.js]
1313
var C = (function () {
@@ -16,8 +16,8 @@ var C = (function () {
1616
}
1717
return C;
1818
}());
19-
// x should not be an optional property
20-
var v = {}; // Should fail
19+
// x should be an optional property
20+
var v = {}; // Should succeed
2121
var v2;
22-
v = v2; // Should fail
23-
var v3 = new C; // Should succeed
22+
v = v2; // Should succeed
23+
var v3 = new C; // Should fail
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// @strictNullChecks: true
2+
3+
class C {
4+
p: number;
5+
}
6+
7+
class D extends C {
8+
constructor(public p?: number) {
9+
super();
10+
}
11+
}

tests/cases/compiler/propertyParameterWithQuestionMark.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ class C {
22
constructor(public x?) { }
33
}
44

5-
// x should not be an optional property
6-
var v: C = {}; // Should fail
5+
// x should be an optional property
6+
var v: C = {}; // Should succeed
77
var v2: { x? }
8-
v = v2; // Should fail
9-
var v3: { x } = new C; // Should succeed
8+
v = v2; // Should succeed
9+
var v3: { x } = new C; // Should fail

0 commit comments

Comments
 (0)