Merge pull request #8825 from Microsoft/Fix8795-1

Fix #8795: make properties defined in optional constructor parameters optional
This commit is contained in:
Mohamed Hegazy 2016-05-25 17:11:57 -07:00
commit 6173696b25
10 changed files with 186 additions and 45 deletions

View file

@ -2027,7 +2027,7 @@ namespace ts {
// containing class.
if (isParameterPropertyDeclaration(node)) {
const classDeclaration = <ClassLikeDeclaration>node.parent.parent;
declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
}
}

View file

@ -1,17 +0,0 @@
tests/cases/compiler/assignmentCompatability10.ts(9,1): error TS2322: Type 'interfaceWithPublicAndOptional<number, string>' is not assignable to type 'classWithPublicAndOptional<number, string>'.
Property 'two' is optional in type 'interfaceWithPublicAndOptional<number, string>' but required in type 'classWithPublicAndOptional<number, string>'.
==== tests/cases/compiler/assignmentCompatability10.ts (1 errors) ====
module __test1__ {
export interface interfaceWithPublicAndOptional<T,U> { one: T; two?: U; }; var obj4: interfaceWithPublicAndOptional<number,string> = { one: 1 };;
export var __val__obj4 = obj4;
}
module __test2__ {
export class classWithPublicAndOptional<T,U> { constructor(public one: T, public two?: U) {} } var x4 = new classWithPublicAndOptional<number, string>(1);;
export var __val__x4 = x4;
}
__test2__.__val__x4 = __test1__.__val__obj4
~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'interfaceWithPublicAndOptional<number, string>' is not assignable to type 'classWithPublicAndOptional<number, string>'.
!!! error TS2322: Property 'two' is optional in type 'interfaceWithPublicAndOptional<number, string>' but required in type 'classWithPublicAndOptional<number, string>'.

View file

@ -0,0 +1,46 @@
=== tests/cases/compiler/assignmentCompatability10.ts ===
module __test1__ {
>__test1__ : Symbol(__test1__, Decl(assignmentCompatability10.ts, 0, 0))
export interface interfaceWithPublicAndOptional<T,U> { one: T; two?: U; }; var obj4: interfaceWithPublicAndOptional<number,string> = { one: 1 };;
>interfaceWithPublicAndOptional : Symbol(interfaceWithPublicAndOptional, Decl(assignmentCompatability10.ts, 0, 18))
>T : Symbol(T, Decl(assignmentCompatability10.ts, 1, 52))
>U : Symbol(U, Decl(assignmentCompatability10.ts, 1, 54))
>one : Symbol(interfaceWithPublicAndOptional.one, Decl(assignmentCompatability10.ts, 1, 58))
>T : Symbol(T, Decl(assignmentCompatability10.ts, 1, 52))
>two : Symbol(interfaceWithPublicAndOptional.two, Decl(assignmentCompatability10.ts, 1, 66))
>U : Symbol(U, Decl(assignmentCompatability10.ts, 1, 54))
>obj4 : Symbol(obj4, Decl(assignmentCompatability10.ts, 1, 83))
>interfaceWithPublicAndOptional : Symbol(interfaceWithPublicAndOptional, Decl(assignmentCompatability10.ts, 0, 18))
>one : Symbol(one, Decl(assignmentCompatability10.ts, 1, 139))
export var __val__obj4 = obj4;
>__val__obj4 : Symbol(__val__obj4, Decl(assignmentCompatability10.ts, 2, 14))
>obj4 : Symbol(obj4, Decl(assignmentCompatability10.ts, 1, 83))
}
module __test2__ {
>__test2__ : Symbol(__test2__, Decl(assignmentCompatability10.ts, 3, 1))
export class classWithPublicAndOptional<T,U> { constructor(public one: T, public two?: U) {} } var x4 = new classWithPublicAndOptional<number, string>(1);;
>classWithPublicAndOptional : Symbol(classWithPublicAndOptional, Decl(assignmentCompatability10.ts, 4, 18))
>T : Symbol(T, Decl(assignmentCompatability10.ts, 5, 44))
>U : Symbol(U, Decl(assignmentCompatability10.ts, 5, 46))
>one : Symbol(classWithPublicAndOptional.one, Decl(assignmentCompatability10.ts, 5, 63))
>T : Symbol(T, Decl(assignmentCompatability10.ts, 5, 44))
>two : Symbol(classWithPublicAndOptional.two, Decl(assignmentCompatability10.ts, 5, 77))
>U : Symbol(U, Decl(assignmentCompatability10.ts, 5, 46))
>x4 : Symbol(x4, Decl(assignmentCompatability10.ts, 5, 104))
>classWithPublicAndOptional : Symbol(classWithPublicAndOptional, Decl(assignmentCompatability10.ts, 4, 18))
export var __val__x4 = x4;
>__val__x4 : Symbol(__val__x4, Decl(assignmentCompatability10.ts, 6, 14))
>x4 : Symbol(x4, Decl(assignmentCompatability10.ts, 5, 104))
}
__test2__.__val__x4 = __test1__.__val__obj4
>__test2__.__val__x4 : Symbol(__test2__.__val__x4, Decl(assignmentCompatability10.ts, 6, 14))
>__test2__ : Symbol(__test2__, Decl(assignmentCompatability10.ts, 3, 1))
>__val__x4 : Symbol(__test2__.__val__x4, Decl(assignmentCompatability10.ts, 6, 14))
>__test1__.__val__obj4 : Symbol(__test1__.__val__obj4, Decl(assignmentCompatability10.ts, 2, 14))
>__test1__ : Symbol(__test1__, Decl(assignmentCompatability10.ts, 0, 0))
>__val__obj4 : Symbol(__test1__.__val__obj4, Decl(assignmentCompatability10.ts, 2, 14))

View file

@ -0,0 +1,51 @@
=== tests/cases/compiler/assignmentCompatability10.ts ===
module __test1__ {
>__test1__ : typeof __test1__
export interface interfaceWithPublicAndOptional<T,U> { one: T; two?: U; }; var obj4: interfaceWithPublicAndOptional<number,string> = { one: 1 };;
>interfaceWithPublicAndOptional : interfaceWithPublicAndOptional<T, U>
>T : T
>U : U
>one : T
>T : T
>two : U
>U : U
>obj4 : interfaceWithPublicAndOptional<number, string>
>interfaceWithPublicAndOptional : interfaceWithPublicAndOptional<T, U>
>{ one: 1 } : { one: number; }
>one : number
>1 : number
export var __val__obj4 = obj4;
>__val__obj4 : interfaceWithPublicAndOptional<number, string>
>obj4 : interfaceWithPublicAndOptional<number, string>
}
module __test2__ {
>__test2__ : typeof __test2__
export class classWithPublicAndOptional<T,U> { constructor(public one: T, public two?: U) {} } var x4 = new classWithPublicAndOptional<number, string>(1);;
>classWithPublicAndOptional : classWithPublicAndOptional<T, U>
>T : T
>U : U
>one : T
>T : T
>two : U
>U : U
>x4 : classWithPublicAndOptional<number, string>
>new classWithPublicAndOptional<number, string>(1) : classWithPublicAndOptional<number, string>
>classWithPublicAndOptional : typeof classWithPublicAndOptional
>1 : number
export var __val__x4 = x4;
>__val__x4 : classWithPublicAndOptional<number, string>
>x4 : classWithPublicAndOptional<number, string>
}
__test2__.__val__x4 = __test1__.__val__obj4
>__test2__.__val__x4 = __test1__.__val__obj4 : __test1__.interfaceWithPublicAndOptional<number, string>
>__test2__.__val__x4 : __test2__.classWithPublicAndOptional<number, string>
>__test2__ : typeof __test2__
>__val__x4 : __test2__.classWithPublicAndOptional<number, string>
>__test1__.__val__obj4 : __test1__.interfaceWithPublicAndOptional<number, string>
>__test1__ : typeof __test1__
>__val__obj4 : __test1__.interfaceWithPublicAndOptional<number, string>

View file

@ -0,0 +1,23 @@
tests/cases/compiler/optionalParameterProperty.ts(6,7): error TS2415: Class 'D' incorrectly extends base class 'C'.
Types of property 'p' are incompatible.
Type 'number | undefined' is not assignable to type 'number'.
Type 'undefined' is not assignable to type 'number'.
==== tests/cases/compiler/optionalParameterProperty.ts (1 errors) ====
class C {
p: number;
}
class D extends C {
~
!!! error TS2415: Class 'D' incorrectly extends base class 'C'.
!!! error TS2415: Types of property 'p' are incompatible.
!!! error TS2415: Type 'number | undefined' is not assignable to type 'number'.
!!! error TS2415: Type 'undefined' is not assignable to type 'number'.
constructor(public p?: number) {
super();
}
}

View file

@ -0,0 +1,32 @@
//// [optionalParameterProperty.ts]
class C {
p: number;
}
class D extends C {
constructor(public p?: number) {
super();
}
}
//// [optionalParameterProperty.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var C = (function () {
function C() {
}
return C;
}());
var D = (function (_super) {
__extends(D, _super);
function D(p) {
_super.call(this);
this.p = p;
}
return D;
}(C));

View file

@ -1,22 +1,17 @@
tests/cases/compiler/propertyParameterWithQuestionMark.ts(6,5): error TS2322: Type '{}' is not assignable to type 'C'.
Property 'x' is missing in type '{}'.
tests/cases/compiler/propertyParameterWithQuestionMark.ts(8,1): error TS2322: Type '{ x?: any; }' is not assignable to type 'C'.
Property 'x' is optional in type '{ x?: any; }' but required in type 'C'.
tests/cases/compiler/propertyParameterWithQuestionMark.ts(9,5): error TS2322: Type 'C' is not assignable to type '{ x: any; }'.
Property 'x' is optional in type 'C' but required in type '{ x: any; }'.
==== tests/cases/compiler/propertyParameterWithQuestionMark.ts (2 errors) ====
==== tests/cases/compiler/propertyParameterWithQuestionMark.ts (1 errors) ====
class C {
constructor(public x?) { }
}
// x should not be an optional property
var v: C = {}; // Should fail
~
!!! error TS2322: Type '{}' is not assignable to type 'C'.
!!! error TS2322: Property 'x' is missing in type '{}'.
// x should be an optional property
var v: C = {}; // Should succeed
var v2: { x? }
v = v2; // Should fail
~
!!! error TS2322: Type '{ x?: any; }' is not assignable to type 'C'.
!!! error TS2322: Property 'x' is optional in type '{ x?: any; }' but required in type 'C'.
var v3: { x } = new C; // Should succeed
v = v2; // Should succeed
var v3: { x } = new C; // Should fail
~~
!!! error TS2322: Type 'C' is not assignable to type '{ x: any; }'.
!!! error TS2322: Property 'x' is optional in type 'C' but required in type '{ x: any; }'.

View file

@ -3,11 +3,11 @@ class C {
constructor(public x?) { }
}
// x should not be an optional property
var v: C = {}; // Should fail
// x should be an optional property
var v: C = {}; // Should succeed
var v2: { x? }
v = v2; // Should fail
var v3: { x } = new C; // Should succeed
v = v2; // Should succeed
var v3: { x } = new C; // Should fail
//// [propertyParameterWithQuestionMark.js]
var C = (function () {
@ -16,8 +16,8 @@ var C = (function () {
}
return C;
}());
// x should not be an optional property
var v = {}; // Should fail
// x should be an optional property
var v = {}; // Should succeed
var v2;
v = v2; // Should fail
var v3 = new C; // Should succeed
v = v2; // Should succeed
var v3 = new C; // Should fail

View file

@ -0,0 +1,11 @@
// @strictNullChecks: true
class C {
p: number;
}
class D extends C {
constructor(public p?: number) {
super();
}
}

View file

@ -2,8 +2,8 @@ class C {
constructor(public x?) { }
}
// x should not be an optional property
var v: C = {}; // Should fail
// x should be an optional property
var v: C = {}; // Should succeed
var v2: { x? }
v = v2; // Should fail
var v3: { x } = new C; // Should succeed
v = v2; // Should succeed
var v3: { x } = new C; // Should fail