From 055ae8cd5ca9838ad03a37f2386802c7cebea1b3 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 21 Dec 2015 14:17:09 -0800 Subject: [PATCH] Contextually type undefined/null/[]/{} Also: 1. Address review comments. 2. Add test cases to implementedPropertyContextualTyping.* 3. Improve some tests: bestCommonTypeOfTuple2 and destructuringParameterDeclaration2. 4. Make some tests worse due to exposing bug 6190: requiredInitializedParameter.*. I'll fix it separately. --- src/compiler/checker.ts | 120 ++++++++++++------ src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 4 + .../reference/bestCommonTypeOfTuple2.types | 2 +- ...tructuringParameterDeclaration2.errors.txt | 16 +-- ...mentedPropertyContextualTyping1.errors.txt | 49 +++++++ .../implementedPropertyContextualTyping1.js | 52 ++++++-- ...plementedPropertyContextualTyping1.symbols | 65 ---------- ...implementedPropertyContextualTyping1.types | 70 ---------- ...mentedPropertyContextualTyping2.errors.txt | 42 ++++-- .../implementedPropertyContextualTyping2.js | 33 ++++- .../requiredInitializedParameter2.errors.txt | 4 +- .../requiredInitializedParameter3.js | 2 +- .../requiredInitializedParameter3.types | 4 +- .../implementedPropertyContextualTyping1.ts | 22 +++- .../implementedPropertyContextualTyping2.ts | 22 +++- 16 files changed, 280 insertions(+), 229 deletions(-) create mode 100644 tests/baselines/reference/implementedPropertyContextualTyping1.errors.txt delete mode 100644 tests/baselines/reference/implementedPropertyContextualTyping1.symbols delete mode 100644 tests/baselines/reference/implementedPropertyContextualTyping1.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 19ff02facb7f3..5e626187edeb2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2593,16 +2593,16 @@ namespace ts { } } - if (declaration.kind === SyntaxKind.PropertyDeclaration) { - const type = getTypeOfBasePropertyDeclaration(declaration); - if (type) { - return type; - } - } - // Use the type of the initializer expression if one is present if (declaration.initializer) { - return checkExpressionCached(declaration.initializer); + let mapper: TypeMapper; + if (declaration.kind === SyntaxKind.PropertyDeclaration) { + const type = getTypeOfBasePropertyDeclaration(declaration); + if (type) { + mapper = createTypeMapper([undefinedType, nullType], [type, type]); + } + } + return checkExpressionCached(declaration.initializer, mapper); } // If it is a short-hand property assignment, use the type of the identifier @@ -2902,29 +2902,35 @@ namespace ts { return unknownType; } - function getTypeOfBasePropertyDeclaration(declaration: VariableLikeDeclaration) { + function getTypeOfBasePropertyDeclaration(declaration: PropertyDeclaration) { if (declaration.parent.kind === SyntaxKind.ClassDeclaration) { - const property = getPropertyFromBaseInterfaces(declaration.parent, declaration.symbol.name); + const property = getPropertyOfBaseTypeDeclaration(declaration.parent, declaration.symbol.name); if (property) { return getTypeOfSymbol(property); } } } - function getPropertyFromBaseInterfaces(declaration: ClassLikeDeclaration, propertyName: string): Symbol { + function getPropertyOfBaseTypeDeclaration(declaration: ClassLikeDeclaration, propertyName: string): Symbol { + const property = getFirstPropertyOfTypes(getBaseTypes(getTypeOfSymbol(getSymbolOfNode(declaration))), propertyName); + if (property) { + return property; + } const implementedTypeNodes = getClassImplementsHeritageClauseElements(declaration); if (implementedTypeNodes) { - for (const typeRefNode of implementedTypeNodes) { - const t = getTypeFromTypeReference(typeRefNode); - if (t !== unknownType) { - for (const property of getPropertiesOfType(t)) { - if (property.valueDeclaration.flags & NodeFlags.Private) { - continue; - } - if (property.name === propertyName) { - return property; - } - } + return getFirstPropertyOfTypes(map(implementedTypeNodes, getTypeFromTypeReference), propertyName); + } + } + + function getFirstPropertyOfTypes(types: Type[], propertyName: string) { + for (const t of types) { + if (t !== unknownType) { + const property = getPropertyOfType(t, propertyName); + if (!property || property.valueDeclaration.flags & NodeFlags.Private) { + continue; + } + if (property.name === propertyName) { + return property; } } } @@ -4968,7 +4974,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: @@ -6929,7 +6935,7 @@ namespace ts { return expression; } - function checkIdentifier(node: Identifier): Type { + function checkIdentifier(node: Identifier, contextualMapper?: TypeMapper): Type { const symbol = getResolvedSymbol(node); // As noted in ECMAScript 6 language spec, arrow functions never have an arguments objects. @@ -6960,7 +6966,11 @@ namespace ts { checkCollisionWithCapturedThisVariable(node, node); checkBlockScopedBindingCapturedInLoop(node, symbol); - return getNarrowedTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol), node); + const type = getNarrowedTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol), node); + if (type === undefinedType || type == nullType) { + return (contextualMapper || identityMapper)(type); + } + return type; } function isInsideFunction(node: Node, threshold: Node): boolean { @@ -7205,10 +7215,14 @@ namespace ts { } } + function checkNullKeyword(nullNode: Node, contextualMapper: TypeMapper) { + return (contextualMapper || identityMapper)(nullType); + } + // Return contextual type of parameter or undefined if no contextual type is available function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type { const func = parameter.parent; - if (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) { + if (isFunctionExpressionOrArrowFunction(func) || isMethod(func)) { if (isContextSensitive(func)) { const contextualSignature = getContextualSignature(func); if (contextualSignature) { @@ -7250,7 +7264,7 @@ namespace ts { } } if (declaration.kind === SyntaxKind.PropertyDeclaration) { - const type = getTypeOfBasePropertyDeclaration(declaration); + const type = getTypeOfBasePropertyDeclaration(declaration); if (type) { return type; } @@ -7585,10 +7599,18 @@ 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)); - const type = isObjectLiteralMethod(node) - ? getContextualTypeForObjectLiteralMethod(node) - : getApparentTypeOfContextualType(node); + Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isMethod(node)); + let type: Type; + if (isFunctionExpressionOrArrowFunction(node)) { + type = getApparentTypeOfContextualType(node); + } + else if (isObjectLiteralMethod(node)) { + type = getContextualTypeForObjectLiteralMethod(node); + } + else if (isMethod(node)) { + type = getTypeOfBasePropertyDeclaration(node); + } + if (!type) { return undefined; } @@ -7681,7 +7703,7 @@ namespace ts { function checkArrayLiteral(node: ArrayLiteralExpression, contextualMapper?: TypeMapper): Type { const elements = node.elements; let hasSpreadElement = false; - const elementTypes: Type[] = []; + let elementTypes: Type[] = []; const inDestructuringPattern = isAssignmentTarget(node); for (const e of elements) { if (inDestructuringPattern && e.kind === SyntaxKind.SpreadElementExpression) { @@ -7743,7 +7765,15 @@ namespace ts { } } } - return createArrayType(elementTypes.length ? getUnionType(elementTypes) : undefinedType); + if (!elementTypes.length) { + const mapper = contextualMapper || identityMapper; + const mappedType = mapper(undefinedType); + if (mappedType === undefinedType) { + return createArrayType(undefinedType); + } + elementTypes = (mappedType).typeArguments; + } + return createArrayType(getUnionType(elementTypes)); } function isNumericName(name: DeclarationName): boolean { @@ -7803,7 +7833,7 @@ namespace ts { return links.resolvedType; } - function checkObjectLiteral(node: ObjectLiteralExpression, contextualMapper?: TypeMapper): Type { + function checkObjectLiteral(node: ObjectLiteralExpression, contextualMapper: TypeMapper): Type { const inDestructuringPattern = isAssignmentTarget(node); // Grammar checking checkGrammarObjectLiteralExpression(node, inDestructuringPattern); @@ -7926,7 +7956,21 @@ namespace ts { } } } - const result = propTypes.length ? getUnionType(propTypes) : undefinedType; + let result: Type; + if (!propTypes.length) { + const mapper = contextualMapper || identityMapper; + const mappedType = mapper(undefinedType); + if (mappedType === undefinedType) { + result = undefinedType; + } + else { + const resolvedType = mappedType; + result = kind === IndexKind.String ? resolvedType.stringIndexType : resolvedType.numberIndexType; + } + } + else { + result = getUnionType(propTypes); + } typeFlags |= result.flags; return result; } @@ -10903,7 +10947,7 @@ namespace ts { return checkExpression((node).initializer, contextualMapper); } - function checkObjectLiteralMethod(node: MethodDeclaration, contextualMapper?: TypeMapper): Type { + function checkObjectLiteralMethod(node: MethodDeclaration, contextualMapper: TypeMapper): Type { // Grammar checking checkGrammarMethod(node); @@ -10978,13 +11022,13 @@ namespace ts { function checkExpressionWorker(node: Expression, contextualMapper: TypeMapper): Type { switch (node.kind) { case SyntaxKind.Identifier: - return checkIdentifier(node); + return checkIdentifier(node, contextualMapper); case SyntaxKind.ThisKeyword: return checkThisExpression(node); case SyntaxKind.SuperKeyword: return checkSuperExpression(node); case SyntaxKind.NullKeyword: - return nullType; + return checkNullKeyword(node, contextualMapper); case SyntaxKind.TrueKeyword: case SyntaxKind.FalseKeyword: return booleanType; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 85ae020753f83..c47df05adcfc8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2291,7 +2291,7 @@ namespace ts { /* @internal */ export interface TypeMapper { - (t: TypeParameter): Type; + (t: Type): Type; instantiations?: Type[]; // Cache of instantiations created using this type mapper. context?: InferenceContext; // The inference context this mapper was created from. // Only inference mappers have this set (in createInferenceMapper). diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index eee09fc641f8c..437cfeba7851c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -697,6 +697,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 getContainingFunction(node: Node): FunctionLikeDeclaration { while (true) { node = node.parent; diff --git a/tests/baselines/reference/bestCommonTypeOfTuple2.types b/tests/baselines/reference/bestCommonTypeOfTuple2.types index 5116a804a4c06..573e346637601 100644 --- a/tests/baselines/reference/bestCommonTypeOfTuple2.types +++ b/tests/baselines/reference/bestCommonTypeOfTuple2.types @@ -29,7 +29,7 @@ class F extends C { f } class C1 implements base1 { i = "foo"; c } >C1 : C1 >base1 : base1 ->i : any +>i : string >"foo" : string >c : any diff --git a/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt index c8037255a3293..33ea55805f6d4 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt @@ -44,13 +44,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; c: any; }' is not assignable to type '{ x: any; y: any; z: any; }'. - Property 'z' is missing in type '{ x: any; y: any; c: 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'. @@ -175,17 +170,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; c: any; }' is not assignable to type '{ x: any; y: any; z: any; }'. -!!! error TS2420: Property 'z' is missing in type '{ x: any; y: any; c: 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]) { } } diff --git a/tests/baselines/reference/implementedPropertyContextualTyping1.errors.txt b/tests/baselines/reference/implementedPropertyContextualTyping1.errors.txt new file mode 100644 index 0000000000000..4609219197456 --- /dev/null +++ b/tests/baselines/reference/implementedPropertyContextualTyping1.errors.txt @@ -0,0 +1,49 @@ +tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts(21,3): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts(24,3): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts(28,3): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts(31,3): error TS2322: Type 'number' is not assignable to type 'string'. + + +==== tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts (4 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; + } + + abstract class Watcher { + abstract watch(e: Event): number; + } + + class Alarm extends Watcher implements Listener, Ringer { + 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; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/implementedPropertyContextualTyping1.js b/tests/baselines/reference/implementedPropertyContextualTyping1.js index b33863a47525c..b563d203c16b1 100644 --- a/tests/baselines/reference/implementedPropertyContextualTyping1.js +++ b/tests/baselines/reference/implementedPropertyContextualTyping1.js @@ -1,6 +1,6 @@ //// [implementedPropertyContextualTyping1.ts] interface Event { - time: number + time: number; } interface Base { superHandle: (e: Event) => number; @@ -12,30 +12,58 @@ interface Ringer { ring: (times: number) => void; } -class Alarm implements Listener, Ringer { - handle = e => { - let n: number = e.time; +abstract class Watcher { + abstract watch(e: Event): number; +} + +class Alarm extends Watcher implements Listener, Ringer { + str: string; + handle = e => { + this.str = e.time; // error } superHandle = e => { + this.str = e.time; // error return e.time; } - ring = times => { - let m: number = times + 1; + ring(times) { + this.str = times; // error + } + watch(e) { + this.str = e.time; // error + return e.time; } } //// [implementedPropertyContextualTyping1.js] -var Alarm = (function () { +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) { - var n = e.time; + _this.str = e.time; // error }; this.superHandle = function (e) { + _this.str = e.time; // error return e.time; }; - this.ring = function (times) { - var m = times + 1; - }; } + Alarm.prototype.ring = function (times) { + this.str = times; // error + }; + Alarm.prototype.watch = function (e) { + this.str = e.time; // error + return e.time; + }; return Alarm; -}()); +}(Watcher)); diff --git a/tests/baselines/reference/implementedPropertyContextualTyping1.symbols b/tests/baselines/reference/implementedPropertyContextualTyping1.symbols deleted file mode 100644 index a9994c46acf2c..0000000000000 --- a/tests/baselines/reference/implementedPropertyContextualTyping1.symbols +++ /dev/null @@ -1,65 +0,0 @@ -=== tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts === -interface Event { ->Event : Symbol(Event, Decl(implementedPropertyContextualTyping1.ts, 0, 0)) - - time: number ->time : Symbol(time, Decl(implementedPropertyContextualTyping1.ts, 0, 17)) -} -interface Base { ->Base : Symbol(Base, Decl(implementedPropertyContextualTyping1.ts, 2, 1)) - - superHandle: (e: Event) => number; ->superHandle : Symbol(superHandle, Decl(implementedPropertyContextualTyping1.ts, 3, 16)) ->e : Symbol(e, Decl(implementedPropertyContextualTyping1.ts, 4, 15)) ->Event : Symbol(Event, Decl(implementedPropertyContextualTyping1.ts, 0, 0)) -} -interface Listener extends Base { ->Listener : Symbol(Listener, Decl(implementedPropertyContextualTyping1.ts, 5, 1)) ->Base : Symbol(Base, Decl(implementedPropertyContextualTyping1.ts, 2, 1)) - - handle: (e: Event) => void; ->handle : Symbol(handle, Decl(implementedPropertyContextualTyping1.ts, 6, 33)) ->e : Symbol(e, Decl(implementedPropertyContextualTyping1.ts, 7, 10)) ->Event : Symbol(Event, Decl(implementedPropertyContextualTyping1.ts, 0, 0)) -} -interface Ringer { ->Ringer : Symbol(Ringer, Decl(implementedPropertyContextualTyping1.ts, 8, 1)) - - ring: (times: number) => void; ->ring : Symbol(ring, Decl(implementedPropertyContextualTyping1.ts, 9, 18)) ->times : Symbol(times, Decl(implementedPropertyContextualTyping1.ts, 10, 8)) -} - -class Alarm implements Listener, Ringer { ->Alarm : Symbol(Alarm, Decl(implementedPropertyContextualTyping1.ts, 11, 1)) ->Listener : Symbol(Listener, Decl(implementedPropertyContextualTyping1.ts, 5, 1)) ->Ringer : Symbol(Ringer, Decl(implementedPropertyContextualTyping1.ts, 8, 1)) - - handle = e => { ->handle : Symbol(handle, Decl(implementedPropertyContextualTyping1.ts, 13, 41)) ->e : Symbol(e, Decl(implementedPropertyContextualTyping1.ts, 14, 9)) - - let n: number = e.time; ->n : Symbol(n, Decl(implementedPropertyContextualTyping1.ts, 15, 5)) ->e.time : Symbol(Event.time, Decl(implementedPropertyContextualTyping1.ts, 0, 17)) ->e : Symbol(e, Decl(implementedPropertyContextualTyping1.ts, 14, 9)) ->time : Symbol(Event.time, Decl(implementedPropertyContextualTyping1.ts, 0, 17)) - } - superHandle = e => { ->superHandle : Symbol(superHandle, Decl(implementedPropertyContextualTyping1.ts, 16, 2)) ->e : Symbol(e, Decl(implementedPropertyContextualTyping1.ts, 17, 14)) - - return e.time; ->e.time : Symbol(Event.time, Decl(implementedPropertyContextualTyping1.ts, 0, 17)) ->e : Symbol(e, Decl(implementedPropertyContextualTyping1.ts, 17, 14)) ->time : Symbol(Event.time, Decl(implementedPropertyContextualTyping1.ts, 0, 17)) - } - ring = times => { ->ring : Symbol(ring, Decl(implementedPropertyContextualTyping1.ts, 19, 2)) ->times : Symbol(times, Decl(implementedPropertyContextualTyping1.ts, 20, 7)) - - let m: number = times + 1; ->m : Symbol(m, Decl(implementedPropertyContextualTyping1.ts, 21, 5)) ->times : Symbol(times, Decl(implementedPropertyContextualTyping1.ts, 20, 7)) - } -} diff --git a/tests/baselines/reference/implementedPropertyContextualTyping1.types b/tests/baselines/reference/implementedPropertyContextualTyping1.types deleted file mode 100644 index e7d5d51dc0f9f..0000000000000 --- a/tests/baselines/reference/implementedPropertyContextualTyping1.types +++ /dev/null @@ -1,70 +0,0 @@ -=== tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts === -interface Event { ->Event : Event - - time: number ->time : number -} -interface Base { ->Base : Base - - superHandle: (e: Event) => number; ->superHandle : (e: Event) => number ->e : Event ->Event : Event -} -interface Listener extends Base { ->Listener : Listener ->Base : Base - - handle: (e: Event) => void; ->handle : (e: Event) => void ->e : Event ->Event : Event -} -interface Ringer { ->Ringer : Ringer - - ring: (times: number) => void; ->ring : (times: number) => void ->times : number -} - -class Alarm implements Listener, Ringer { ->Alarm : Alarm ->Listener : Listener ->Ringer : Ringer - - handle = e => { ->handle : (e: Event) => void ->e => { let n: number = e.time; } : (e: Event) => void ->e : Event - - let n: number = e.time; ->n : number ->e.time : number ->e : Event ->time : number - } - superHandle = e => { ->superHandle : (e: Event) => number ->e => { return e.time; } : (e: Event) => number ->e : Event - - return e.time; ->e.time : number ->e : Event ->time : number - } - ring = times => { ->ring : (times: number) => void ->times => { let m: number = times + 1; } : (times: number) => void ->times : number - - let m: number = times + 1; ->m : number ->times + 1 : number ->times : number ->1 : number - } -} diff --git a/tests/baselines/reference/implementedPropertyContextualTyping2.errors.txt b/tests/baselines/reference/implementedPropertyContextualTyping2.errors.txt index f58e9e70a6a84..b9afdbad44936 100644 --- a/tests/baselines/reference/implementedPropertyContextualTyping2.errors.txt +++ b/tests/baselines/reference/implementedPropertyContextualTyping2.errors.txt @@ -1,15 +1,41 @@ -tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts(9,1): error TS2322: Type 'string' is not assignable to type 'number'. +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]'. + Property '0' is missing in type '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 (1 errors) ==== +==== tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts (4 errors) ==== interface Long { length: number; } - - class Cat implements Long { + 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 longCat = new Cat(); - longCat.length = "wat"; - ~~~~~~~~~~~~~~ -!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file + 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]'. +!!! error TS2322: Property '0' is missing in type 'Number'. + lolCat.invisibles.push(0); + ~ +!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/implementedPropertyContextualTyping2.js b/tests/baselines/reference/implementedPropertyContextualTyping2.js index cd3595b417678..a78f081b83d56 100644 --- a/tests/baselines/reference/implementedPropertyContextualTyping2.js +++ b/tests/baselines/reference/implementedPropertyContextualTyping2.js @@ -2,19 +2,40 @@ interface Long { length: number; } - -class Cat implements Long { +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 longCat = new Cat(); -longCat.length = "wat"; +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 longCat = new Cat(); -longCat.length = "wat"; +var lolCat = new Cat(); +lolCat.length = "wat"; +lolCat.canhaz = false; +lolCat.location['ceiling'] = -1; +lolCat.invisibles.push(0); diff --git a/tests/baselines/reference/requiredInitializedParameter2.errors.txt b/tests/baselines/reference/requiredInitializedParameter2.errors.txt index 5dcec536e1b67..48994b9fc32f0 100644 --- a/tests/baselines/reference/requiredInitializedParameter2.errors.txt +++ b/tests/baselines/reference/requiredInitializedParameter2.errors.txt @@ -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) { } } \ No newline at end of file diff --git a/tests/baselines/reference/requiredInitializedParameter3.js b/tests/baselines/reference/requiredInitializedParameter3.js index 983955b79e832..231ab46ec6d97 100644 --- a/tests/baselines/reference/requiredInitializedParameter3.js +++ b/tests/baselines/reference/requiredInitializedParameter3.js @@ -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; } diff --git a/tests/baselines/reference/requiredInitializedParameter3.types b/tests/baselines/reference/requiredInitializedParameter3.types index aa37f5e13ddb3..9c30188f2b729 100644 --- a/tests/baselines/reference/requiredInitializedParameter3.types +++ b/tests/baselines/reference/requiredInitializedParameter3.types @@ -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 } diff --git a/tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts b/tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts index 4160e833418b4..e2816569eeb2b 100644 --- a/tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts +++ b/tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping1.ts @@ -1,5 +1,5 @@ interface Event { - time: number + time: number; } interface Base { superHandle: (e: Event) => number; @@ -11,14 +11,24 @@ interface Ringer { ring: (times: number) => void; } -class Alarm implements Listener, Ringer { - handle = e => { - let n: number = e.time; +abstract class Watcher { + abstract watch(e: Event): number; +} + +class Alarm extends Watcher implements Listener, Ringer { + str: string; + handle = e => { + this.str = e.time; // error } superHandle = e => { + this.str = e.time; // error return e.time; } - ring = times => { - let m: number = times + 1; + ring(times) { + this.str = times; // error + } + watch(e) { + this.str = e.time; // error + return e.time; } } \ No newline at end of file diff --git a/tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts b/tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts index 38e1652d9f052..465d5da931c1b 100644 --- a/tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts +++ b/tests/cases/conformance/expressions/contextualTyping/implementedPropertyContextualTyping2.ts @@ -1,9 +1,23 @@ interface Long { length: number; } - -class Cat implements Long { +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 longCat = new Cat(); -longCat.length = "wat"; \ No newline at end of file +const lolCat = new Cat(); +lolCat.length = "wat"; +lolCat.canhaz = false; +lolCat.location['ceiling'] = -1; +lolCat.invisibles.push(0);