Compare commits

...

9 commits

Author SHA1 Message Date
Nathan Shively-Sanders 270843ffce Improve variable names in getTypeOfBasePropertyDeclaration 2016-08-30 10:37:00 -07:00
Nathan Shively-Sanders 5872fdbf25 Update baselines and clean up tests 2016-08-30 10:25:07 -07:00
Nathan Shively-Sanders 02e5a31b40 Clean up getTypeOfBasePropertyDeclaration
it now uses intersections, which is much cleaner to write
2016-08-30 10:24:04 -07:00
Nathan Shively-Sanders 958c6afa00 Update new test baselines for inherited properties after merge 2016-08-30 08:44:20 -07:00
Nathan Shively-Sanders 3747e2969f Merge branch 'master' into contextually-type-inherited-properties-WIP 2016-08-30 08:39:41 -07:00
Nathan Shively-Sanders fd8819a333 Adds tests and fix a couple of bugs 2016-05-02 12:02:34 -07:00
Nathan Shively-Sanders d9392e9443 Update baselines
The new baselines expose a problem: contextually typing a method with an
default parameter now ignores the type of the default parameter's
initialiser. For example,

```ts
interface I {
 m(): void;
}
class C implements I {
  m(a = 0, b?) { }
}
```

gives both `a` and `b` the type `any`, even though `a` could have the type
`number` inferred from its initialiser.
2016-04-30 20:45:52 -07:00
Nathan Shively-Sanders 0181886d10 Merge branch 'master' into contextually-type-inherited-properties-WIP 2016-04-30 11:09:02 -07:00
Nathan Shively-Sanders ea43f4626b First draft
Doesn't work yet. Stopping to revert this: any in contextual signatures
which breaks a lot of code that isn't this: annotated.
2016-04-29 15:14:55 -07:00
22 changed files with 584 additions and 49 deletions

View file

@ -3051,6 +3051,14 @@ namespace ts {
return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ declaration.questionToken && includeOptionality);
}
// use type from base class' property if present
if (declaration.kind === SyntaxKind.PropertyDeclaration) {
const type = getTypeOfBasePropertyDeclaration(<PropertyDeclaration>declaration);
if (type) {
return type;
}
}
if (declaration.kind === SyntaxKind.Parameter) {
const func = <FunctionLikeDeclaration>declaration.parent;
// For a parameter of a set accessor, use the type of the get accessor if one is present
@ -3434,6 +3442,20 @@ namespace ts {
return unknownType;
}
function getTypeOfBasePropertyDeclaration(declaration: PropertyDeclaration) {
if (declaration.parent.kind === SyntaxKind.ClassDeclaration) {
const parent = <ClassLikeDeclaration>declaration.parent;
const baseClasses = getBaseTypes(<InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(parent)));
const implementsNode = getClassImplementsHeritageClauseElements(parent) || ([] as NodeArray<ExpressionWithTypeArguments>);
const allBases = getIntersectionType(baseClasses.concat(map(implementsNode, getTypeFromTypeReference)));
const baseProperty = getPropertyOfType(allBases, declaration.symbol.name);
if (baseProperty) {
return getTypeOfSymbol(baseProperty);
}
}
return undefined;
}
function getTargetType(type: ObjectType): Type {
return type.flags & TypeFlags.Reference ? (<TypeReference>type).target : type;
}
@ -5900,7 +5922,7 @@ namespace ts {
// Returns true if the given expression contains (at any level of nesting) a function or arrow expression
// that is subject to contextual typing.
function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElement): boolean {
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isMethod(node));
switch (node.kind) {
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
@ -5933,8 +5955,8 @@ namespace ts {
return !node.typeParameters && areAllParametersUntyped && !isNullaryArrow;
}
function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | MethodDeclaration {
return (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) && isContextSensitiveFunctionLikeDeclaration(func);
function isContextSensitiveFunctionOrMethod(func: Node): func is FunctionExpression | MethodDeclaration {
return (isFunctionExpressionOrArrowFunction(func) || isMethod(func)) && isContextSensitiveFunctionLikeDeclaration(func);
}
function getTypeWithoutSignatures(type: Type): Type {
@ -9376,7 +9398,7 @@ namespace ts {
}
function getContextualThisParameter(func: FunctionLikeDeclaration): Symbol {
if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
if (isContextSensitiveFunctionOrMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
const contextualSignature = getContextualSignature(func);
if (contextualSignature) {
return contextualSignature.thisParameter;
@ -9389,7 +9411,7 @@ namespace ts {
// Return contextual type of parameter or undefined if no contextual type is available
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
const func = parameter.parent;
if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
if (isContextSensitiveFunctionOrMethod(func)) {
const iife = getImmediatelyInvokedFunctionExpression(func);
if (iife) {
const indexOfParameter = indexOf(func.parameters, parameter);
@ -9443,6 +9465,12 @@ namespace ts {
if (declaration.type) {
return getTypeFromTypeNode(declaration.type);
}
if (declaration.kind === SyntaxKind.PropertyDeclaration) {
const type = getTypeOfBasePropertyDeclaration(<PropertyDeclaration>declaration);
if (type) {
return type;
}
}
if (declaration.kind === SyntaxKind.Parameter) {
const type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
if (type) {
@ -9816,16 +9844,22 @@ namespace ts {
}
function getContextualSignatureForFunctionLikeDeclaration(node: FunctionLikeDeclaration): Signature {
// Only function expressions, arrow functions, and object literal methods are contextually typed.
return isFunctionExpressionOrArrowFunction(node) || isObjectLiteralMethod(node)
// Only function expressions, arrow functions, and methods are contextually typed.
return isFunctionExpressionOrArrowFunction(node) || isMethod(node)
? getContextualSignature(<FunctionExpression>node)
: undefined;
}
function getContextualTypeForFunctionLikeDeclaration(node: FunctionExpression | MethodDeclaration) {
return isObjectLiteralMethod(node) ?
getContextualTypeForObjectLiteralMethod(node) :
getApparentTypeOfContextualType(node);
if (isFunctionExpressionOrArrowFunction(node)) {
return getApparentTypeOfContextualType(node);
}
else if (isObjectLiteralMethod(node)) {
return getContextualTypeForObjectLiteralMethod(node);
}
else if (isMethod(node)) {
return getTypeOfBasePropertyDeclaration(node);
}
}
// Return the contextual signature for a given expression node. A contextual type provides a
@ -9834,7 +9868,7 @@ namespace ts {
// all identical ignoring their return type, the result is same signature but with return type as
// union type of return types from these signatures
function getContextualSignature(node: FunctionExpression | MethodDeclaration): Signature {
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isMethod(node));
const type = getContextualTypeForFunctionLikeDeclaration(node);
if (!type) {
return undefined;

View file

@ -864,6 +864,10 @@ namespace ts {
return predicate && predicate.kind === TypePredicateKind.Identifier;
}
export function isMethod(node: Node): node is MethodDeclaration {
return node && node.kind === SyntaxKind.MethodDeclaration;
}
export function isThisTypePredicate(predicate: TypePredicate): predicate is ThisTypePredicate {
return predicate && predicate.kind === TypePredicateKind.This;
}

View file

@ -7,15 +7,11 @@ tests/cases/compiler/abstractPropertyNegative.ts(13,7): error TS2515: Non-abstra
tests/cases/compiler/abstractPropertyNegative.ts(15,5): error TS1244: Abstract methods can only appear within an abstract class.
tests/cases/compiler/abstractPropertyNegative.ts(16,37): error TS1005: '{' expected.
tests/cases/compiler/abstractPropertyNegative.ts(19,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
tests/cases/compiler/abstractPropertyNegative.ts(24,7): error TS2415: Class 'WrongTypePropertyImpl' incorrectly extends base class 'WrongTypeProperty'.
Types of property 'num' are incompatible.
Type 'string' is not assignable to type 'number'.
tests/cases/compiler/abstractPropertyNegative.ts(25,5): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/compiler/abstractPropertyNegative.ts(30,7): error TS2415: Class 'WrongTypeAccessorImpl' incorrectly extends base class 'WrongTypeAccessor'.
Types of property 'num' are incompatible.
Type 'string' is not assignable to type 'number'.
tests/cases/compiler/abstractPropertyNegative.ts(33,7): error TS2415: Class 'WrongTypeAccessorImpl2' incorrectly extends base class 'WrongTypeAccessor'.
Types of property 'num' are incompatible.
Type 'string' is not assignable to type 'number'.
tests/cases/compiler/abstractPropertyNegative.ts(34,5): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/compiler/abstractPropertyNegative.ts(38,18): error TS2676: Accessors must both be abstract or non-abstract.
tests/cases/compiler/abstractPropertyNegative.ts(39,9): error TS2676: Accessors must both be abstract or non-abstract.
tests/cases/compiler/abstractPropertyNegative.ts(40,9): error TS2676: Accessors must both be abstract or non-abstract.
@ -65,11 +61,9 @@ tests/cases/compiler/abstractPropertyNegative.ts(41,18): error TS2676: Accessors
abstract num: number;
}
class WrongTypePropertyImpl extends WrongTypeProperty {
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2415: Class 'WrongTypePropertyImpl' incorrectly extends base class 'WrongTypeProperty'.
!!! error TS2415: Types of property 'num' are incompatible.
!!! error TS2415: Type 'string' is not assignable to type 'number'.
num = "nope, wrong";
~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'number'.
}
abstract class WrongTypeAccessor {
abstract get num(): number;
@ -82,11 +76,9 @@ tests/cases/compiler/abstractPropertyNegative.ts(41,18): error TS2676: Accessors
get num() { return "nope, wrong"; }
}
class WrongTypeAccessorImpl2 extends WrongTypeAccessor {
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2415: Class 'WrongTypeAccessorImpl2' incorrectly extends base class 'WrongTypeAccessor'.
!!! error TS2415: Types of property 'num' are incompatible.
!!! error TS2415: Type 'string' is not assignable to type 'number'.
num = "nope, wrong";
~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'number'.
}
abstract class AbstractAccessorMismatch {

View file

@ -29,7 +29,7 @@ class D extends C<IHasVisualizationModel> {
>IHasVisualizationModel : IHasVisualizationModel
x = moduleA;
>x : typeof moduleA
>x : IHasVisualizationModel
>moduleA : typeof moduleA
}
=== tests/cases/compiler/aliasUsageInTypeArgumentOfExtendsClause_backbone.ts ===

View file

@ -29,14 +29,14 @@ class F extends C { f }
class C1 implements base1 { i = "foo"; c }
>C1 : C1
>base1 : base1
>i : string
>i : any
>"foo" : string
>c : any
class D1 extends C1 { i = "bar"; d }
>D1 : D1
>C1 : C1
>i : string
>i : any
>"bar" : string
>d : any

View file

@ -1,3 +1,4 @@
tests/cases/compiler/convertKeywordsYes.ts(175,5): error TS2322: Type 'number' is not assignable to type 'Function'.
tests/cases/compiler/convertKeywordsYes.ts(292,11): error TS1213: Identifier expected. 'implements' is a reserved word in strict mode. Class definitions are automatically in strict mode.
tests/cases/compiler/convertKeywordsYes.ts(293,11): error TS1213: Identifier expected. 'interface' is a reserved word in strict mode. Class definitions are automatically in strict mode.
tests/cases/compiler/convertKeywordsYes.ts(294,11): error TS1213: Identifier expected. 'let' is a reserved word in strict mode. Class definitions are automatically in strict mode.
@ -9,7 +10,7 @@ tests/cases/compiler/convertKeywordsYes.ts(301,11): error TS1213: Identifier exp
tests/cases/compiler/convertKeywordsYes.ts(303,11): error TS1213: Identifier expected. 'yield' is a reserved word in strict mode. Class definitions are automatically in strict mode.
==== tests/cases/compiler/convertKeywordsYes.ts (9 errors) ====
==== tests/cases/compiler/convertKeywordsYes.ts (10 errors) ====
// reserved ES5 future in strict mode
var constructor = 0;
@ -185,6 +186,8 @@ tests/cases/compiler/convertKeywordsYes.ts(303,11): error TS1213: Identifier exp
class bigClass {
public "constructor" = 0;
~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'Function'.
public any = 0;
public boolean = 0;
public implements = 0;

View file

@ -36,13 +36,8 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(46,13): error TS2463: A binding pattern parameter cannot be optional in an implementation signature.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(47,13): error TS2463: A binding pattern parameter cannot be optional in an implementation signature.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(55,7): error TS2420: Class 'C4' incorrectly implements interface 'F2'.
Types of property 'd4' are incompatible.
Type '({x, y, c}: { x: any; y: any; c: any; }) => void' is not assignable to type '({x, y, z}?: { x: any; y: any; z: any; }) => any'.
Types of parameters '__0' and '__0' are incompatible.
Type '{ x: any; y: any; z: any; }' is not assignable to type '{ x: any; y: any; c: any; }'.
Property 'c' is missing in type '{ x: any; y: any; z: any; }'.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(56,8): error TS2463: A binding pattern parameter cannot be optional in an implementation signature.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(57,15): error TS2459: Type '{ x: any; y: any; z: any; }' has no property 'c' and no string index signature.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(65,18): error TS2300: Duplicate identifier 'number'.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(65,26): error TS2300: Duplicate identifier 'number'.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(65,34): error TS2300: Duplicate identifier 'number'.
@ -159,17 +154,12 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(
}
class C4 implements F2 {
~~
!!! error TS2420: Class 'C4' incorrectly implements interface 'F2'.
!!! error TS2420: Types of property 'd4' are incompatible.
!!! error TS2420: Type '({x, y, c}: { x: any; y: any; c: any; }) => void' is not assignable to type '({x, y, z}?: { x: any; y: any; z: any; }) => any'.
!!! error TS2420: Types of parameters '__0' and '__0' are incompatible.
!!! error TS2420: Type '{ x: any; y: any; z: any; }' is not assignable to type '{ x: any; y: any; c: any; }'.
!!! error TS2420: Property 'c' is missing in type '{ x: any; y: any; z: any; }'.
d3([a, b, c]?) { } // Error, binding pattern can't be optional in implementation signature
~~~~~~~~~~
!!! error TS2463: A binding pattern parameter cannot be optional in an implementation signature.
d4({x, y, c}) { }
~
!!! error TS2459: Type '{ x: any; y: any; z: any; }' has no property 'c' and no string index signature.
e0([a, b, q]) { }
}

View file

@ -0,0 +1,77 @@
tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts(25,9): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts(28,9): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts(32,9): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts(35,9): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts(54,7): error TS7006: Parameter 'n' implicitly has an 'any' type.
==== tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts (5 errors) ====
interface Event {
time: number;
}
interface Base {
superHandle: (e: Event) => number;
}
interface Listener extends Base {
handle: (e: Event) => void;
}
interface Ringer {
ring: (times: number) => void;
}
interface StringLiteral {
literal(): "A";
literals: "A" | "B";
}
abstract class Watcher {
abstract watch(e: Event): number;
}
class Alarm extends Watcher implements Listener, Ringer, StringLiteral {
str: string;
handle = e => {
this.str = e.time; // error
~~~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
}
superHandle = e => {
this.str = e.time; // error
~~~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
return e.time;
}
ring(times) {
this.str = times; // error
~~~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
}
watch(e) {
this.str = e.time; // error
~~~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
return e.time;
}
literal() {
return "A"; // ok: "A" is assignable to "A"
}
literals = "A"; // ok: "A" is assignable to "A" | "B"
}
interface A {
q(n: string): void;
}
interface B {
q(n: number): void;
}
class C {
r: number;
}
class Multiple extends C implements A, B {
q(n) { // error, n is implicitly any because A.q and B.q exist
~
!!! error TS7006: Parameter 'n' implicitly has an 'any' type.
n.length; // and the unioned type has no signature
n.toFixed; // (even though the constituent types each do)
}
}

View file

@ -0,0 +1,114 @@
//// [implementedPropertyContextualTyping1.ts]
interface Event {
time: number;
}
interface Base {
superHandle: (e: Event) => number;
}
interface Listener extends Base {
handle: (e: Event) => void;
}
interface Ringer {
ring: (times: number) => void;
}
interface StringLiteral {
literal(): "A";
literals: "A" | "B";
}
abstract class Watcher {
abstract watch(e: Event): number;
}
class Alarm extends Watcher implements Listener, Ringer, StringLiteral {
str: string;
handle = e => {
this.str = e.time; // error
}
superHandle = e => {
this.str = e.time; // error
return e.time;
}
ring(times) {
this.str = times; // error
}
watch(e) {
this.str = e.time; // error
return e.time;
}
literal() {
return "A"; // ok: "A" is assignable to "A"
}
literals = "A"; // ok: "A" is assignable to "A" | "B"
}
interface A {
q(n: string): void;
}
interface B {
q(n: number): void;
}
class C {
r: number;
}
class Multiple extends C implements A, B {
q(n) { // error, n is implicitly any because A.q and B.q exist
n.length; // and the unioned type has no signature
n.toFixed; // (even though the constituent types each do)
}
}
//// [implementedPropertyContextualTyping1.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 Watcher = (function () {
function Watcher() {
}
return Watcher;
}());
var Alarm = (function (_super) {
__extends(Alarm, _super);
function Alarm() {
var _this = this;
_super.apply(this, arguments);
this.handle = function (e) {
_this.str = e.time; // error
};
this.superHandle = function (e) {
_this.str = e.time; // error
return e.time;
};
this.literals = "A"; // ok: "A" is assignable to "A" | "B"
}
Alarm.prototype.ring = function (times) {
this.str = times; // error
};
Alarm.prototype.watch = function (e) {
this.str = e.time; // error
return e.time;
};
Alarm.prototype.literal = function () {
return "A"; // ok: "A" is assignable to "A"
};
return Alarm;
}(Watcher));
var C = (function () {
function C() {
}
return C;
}());
var Multiple = (function (_super) {
__extends(Multiple, _super);
function Multiple() {
_super.apply(this, arguments);
}
Multiple.prototype.q = function (n) {
n.length; // and the unioned type has no signature
n.toFixed; // (even though the constituent types each do)
};
return Multiple;
}(C));

View file

@ -0,0 +1,39 @@
tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts(20,1): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts(21,1): error TS2322: Type 'boolean' is not assignable to type 'string'.
tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts(22,1): error TS2322: Type 'number' is not assignable to type '[number, number]'.
tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts(23,24): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
==== tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts (4 errors) ====
interface Long {
length: number;
}
interface Lol {
canhaz: string;
}
interface Ceiling {
location: { [coordinates: string]: [number, number] };
}
interface Invisible {
invisibles: string[];
}
class Cat implements Long, Lol, Ceiling, Invisible {
length = undefined;
canhaz = null;
location = {};
invisibles = [];
}
const lolCat = new Cat();
lolCat.length = "wat";
~~~~~~~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'number'.
lolCat.canhaz = false;
~~~~~~~~~~~~~
!!! error TS2322: Type 'boolean' is not assignable to type 'string'.
lolCat.location['ceiling'] = -1;
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'number' is not assignable to type '[number, number]'.
lolCat.invisibles.push(0);
~
!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.

View file

@ -0,0 +1,41 @@
//// [implementedPropertyContextualTyping2.ts]
interface Long {
length: number;
}
interface Lol {
canhaz: string;
}
interface Ceiling {
location: { [coordinates: string]: [number, number] };
}
interface Invisible {
invisibles: string[];
}
class Cat implements Long, Lol, Ceiling, Invisible {
length = undefined;
canhaz = null;
location = {};
invisibles = [];
}
const lolCat = new Cat();
lolCat.length = "wat";
lolCat.canhaz = false;
lolCat.location['ceiling'] = -1;
lolCat.invisibles.push(0);
//// [implementedPropertyContextualTyping2.js]
var Cat = (function () {
function Cat() {
this.length = undefined;
this.canhaz = null;
this.location = {};
this.invisibles = [];
}
return Cat;
}());
var lolCat = new Cat();
lolCat.length = "wat";
lolCat.canhaz = false;
lolCat.location['ceiling'] = -1;
lolCat.invisibles.push(0);

View file

@ -0,0 +1,42 @@
//// [implementedPropertyContextualTyping3.ts]
interface A {
p: string;
r: string;
s: string;
}
interface B {
p: number;
r: boolean;
s: string;
}
class C {
r: number;
}
class Multiple extends C implements A, B {
p = undefined; // ok, Multiple.p: string & number
r = null; // OK, r: string & boolean & number
s = null; // OK, s: string
}
//// [implementedPropertyContextualTyping3.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 Multiple = (function (_super) {
__extends(Multiple, _super);
function Multiple() {
_super.apply(this, arguments);
this.p = undefined; // ok, Multiple.p: string & number
this.r = null; // OK, r: string & boolean & number
this.s = null; // OK, s: string
}
return Multiple;
}(C));

View file

@ -0,0 +1,48 @@
=== tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping3.ts ===
interface A {
>A : Symbol(A, Decl(implementedPropertyContextualTyping3.ts, 0, 0))
p: string;
>p : Symbol(A.p, Decl(implementedPropertyContextualTyping3.ts, 0, 13))
r: string;
>r : Symbol(A.r, Decl(implementedPropertyContextualTyping3.ts, 1, 14))
s: string;
>s : Symbol(A.s, Decl(implementedPropertyContextualTyping3.ts, 2, 14))
}
interface B {
>B : Symbol(B, Decl(implementedPropertyContextualTyping3.ts, 4, 1))
p: number;
>p : Symbol(B.p, Decl(implementedPropertyContextualTyping3.ts, 5, 13))
r: boolean;
>r : Symbol(B.r, Decl(implementedPropertyContextualTyping3.ts, 6, 14))
s: string;
>s : Symbol(B.s, Decl(implementedPropertyContextualTyping3.ts, 7, 15))
}
class C {
>C : Symbol(C, Decl(implementedPropertyContextualTyping3.ts, 9, 1))
r: number;
>r : Symbol(C.r, Decl(implementedPropertyContextualTyping3.ts, 10, 9))
}
class Multiple extends C implements A, B {
>Multiple : Symbol(Multiple, Decl(implementedPropertyContextualTyping3.ts, 12, 1))
>C : Symbol(C, Decl(implementedPropertyContextualTyping3.ts, 9, 1))
>A : Symbol(A, Decl(implementedPropertyContextualTyping3.ts, 0, 0))
>B : Symbol(B, Decl(implementedPropertyContextualTyping3.ts, 4, 1))
p = undefined; // ok, Multiple.p: string & number
>p : Symbol(Multiple.p, Decl(implementedPropertyContextualTyping3.ts, 13, 42))
>undefined : Symbol(undefined)
r = null; // OK, r: string & boolean & number
>r : Symbol(Multiple.r, Decl(implementedPropertyContextualTyping3.ts, 14, 18))
s = null; // OK, s: string
>s : Symbol(Multiple.s, Decl(implementedPropertyContextualTyping3.ts, 15, 13))
}

View file

@ -0,0 +1,50 @@
=== tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping3.ts ===
interface A {
>A : A
p: string;
>p : string
r: string;
>r : string
s: string;
>s : string
}
interface B {
>B : B
p: number;
>p : number
r: boolean;
>r : boolean
s: string;
>s : string
}
class C {
>C : C
r: number;
>r : number
}
class Multiple extends C implements A, B {
>Multiple : Multiple
>C : C
>A : A
>B : B
p = undefined; // ok, Multiple.p: string & number
>p : string & number
>undefined : undefined
r = null; // OK, r: string & boolean & number
>r : number & string & boolean
>null : null
s = null; // OK, s: string
>s : string
>null : null
}

View file

@ -142,6 +142,6 @@ declare class Base {
f?(): number;
}
declare class Derived extends Base {
a: number;
a: number | undefined;
f(): number;
}

View file

@ -216,7 +216,7 @@ class Derived extends Base {
>Base : Base
a = 1;
>a : number
>a : number | undefined
>1 : number
f(): number { return 1; }

View file

@ -1,6 +1,6 @@
tests/cases/compiler/requiredInitializedParameter2.ts(5,7): error TS2420: Class 'C1' incorrectly implements interface 'I1'.
Types of property 'method' are incompatible.
Type '(a: number, b: any) => void' is not assignable to type '() => any'.
Type '(a: any, b: any) => void' is not assignable to type '() => any'.
==== tests/cases/compiler/requiredInitializedParameter2.ts (1 errors) ====
@ -12,6 +12,6 @@ tests/cases/compiler/requiredInitializedParameter2.ts(5,7): error TS2420: Class
~~
!!! error TS2420: Class 'C1' incorrectly implements interface 'I1'.
!!! error TS2420: Types of property 'method' are incompatible.
!!! error TS2420: Type '(a: number, b: any) => void' is not assignable to type '() => any'.
!!! error TS2420: Type '(a: any, b: any) => void' is not assignable to type '() => any'.
method(a = 0, b) { }
}

View file

@ -23,5 +23,5 @@ interface I1 {
method(): any;
}
declare class C1 implements I1 {
method(a?: number, b?: any): void;
method(a?: any, b?: any): void;
}

View file

@ -11,8 +11,8 @@ class C1 implements I1 {
>I1 : I1
method(a = 0, b?) { }
>method : (a?: number, b?: any) => void
>a : number
>method : (a?: any, b?: any) => void
>a : any
>0 : number
>b : any
}

View file

@ -0,0 +1,59 @@
// @noImplicitAny: true
interface Event {
time: number;
}
interface Base {
superHandle: (e: Event) => number;
}
interface Listener extends Base {
handle: (e: Event) => void;
}
interface Ringer {
ring: (times: number) => void;
}
interface StringLiteral {
literal(): "A";
literals: "A" | "B";
}
abstract class Watcher {
abstract watch(e: Event): number;
}
class Alarm extends Watcher implements Listener, Ringer, StringLiteral {
str: string;
handle = e => {
this.str = e.time; // error
}
superHandle = e => {
this.str = e.time; // error
return e.time;
}
ring(times) {
this.str = times; // error
}
watch(e) {
this.str = e.time; // error
return e.time;
}
literal() {
return "A"; // ok: "A" is assignable to "A"
}
literals = "A"; // ok: "A" is assignable to "A" | "B"
}
interface A {
q(n: string): void;
}
interface B {
q(n: number): void;
}
class C {
r: number;
}
class Multiple extends C implements A, B {
q(n) { // error, n is implicitly any because A.q and B.q exist
n.length; // and the unioned type has no signature
n.toFixed; // (even though the constituent types each do)
}
}

View file

@ -0,0 +1,23 @@
interface Long {
length: number;
}
interface Lol {
canhaz: string;
}
interface Ceiling {
location: { [coordinates: string]: [number, number] };
}
interface Invisible {
invisibles: string[];
}
class Cat implements Long, Lol, Ceiling, Invisible {
length = undefined;
canhaz = null;
location = {};
invisibles = [];
}
const lolCat = new Cat();
lolCat.length = "wat";
lolCat.canhaz = false;
lolCat.location['ceiling'] = -1;
lolCat.invisibles.push(0);

View file

@ -0,0 +1,19 @@
// @noImplicitAny: true
interface A {
p: string;
r: string;
s: string;
}
interface B {
p: number;
r: boolean;
s: string;
}
class C {
r: number;
}
class Multiple extends C implements A, B {
p = undefined; // ok, Multiple.p: string & number
r = null; // OK, r: string & boolean & number
s = null; // OK, s: string
}