From 9ff67f636bd3aac488df12b7454191380abbc17d Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 14 Mar 2018 10:57:38 -0700 Subject: [PATCH 01/13] inferFromUsage: Handle being at an unexpected location (#22569) * inferFromUsage: Handle being at an unexpected location * add comment --- src/services/codefixes/inferFromUsage.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 74ad2113dccc7..a79fa5acc6611 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -64,17 +64,21 @@ namespace ts.codefix { return undefined; } + const { parent } = token; switch (errorCode) { // Variable and Property declarations case Diagnostics.Member_0_implicitly_has_an_1_type.code: case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code: - annotateVariableDeclaration(changes, sourceFile, token.parent, program, cancellationToken); - return token.parent as Declaration; + if (isVariableDeclaration(parent) || isPropertyDeclaration(parent) || isPropertySignature(parent)) { // handle bad location + annotateVariableDeclaration(changes, sourceFile, parent, program, cancellationToken); + return parent; + } + return undefined; case Diagnostics.Variable_0_implicitly_has_an_1_type.code: { const symbol = program.getTypeChecker().getSymbolAtLocation(token); - if (symbol && symbol.valueDeclaration) { - annotateVariableDeclaration(changes, sourceFile, symbol.valueDeclaration, program, cancellationToken); + if (symbol && symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration)) { + annotateVariableDeclaration(changes, sourceFile, symbol.valueDeclaration, program, cancellationToken); return symbol.valueDeclaration; } } @@ -95,7 +99,7 @@ namespace ts.codefix { // falls through case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code: if (!seenFunctions || addToSeen(seenFunctions, getNodeId(containingFunction))) { - const param = cast(token.parent, isParameter); + const param = cast(parent, isParameter); annotateParameters(changes, param, containingFunction, sourceFile, program, cancellationToken); return param; } From dc4001f41d0b58d46a3c8fd081907dd87abffef1 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 16 Mar 2018 11:53:17 -0700 Subject: [PATCH 02/13] Fix await code action crashes when await is not in a function (#22623) Fixes #22614 --- src/services/codefixes/fixAwaitInSyncFunction.ts | 4 ++++ .../fourslash/codeFixAwaitShouldNotCrashIfNotInFunction.ts | 5 +++++ 2 files changed, 9 insertions(+) create mode 100644 tests/cases/fourslash/codeFixAwaitShouldNotCrashIfNotInFunction.ts diff --git a/src/services/codefixes/fixAwaitInSyncFunction.ts b/src/services/codefixes/fixAwaitInSyncFunction.ts index 883993e7b5146..713a25456c054 100644 --- a/src/services/codefixes/fixAwaitInSyncFunction.ts +++ b/src/services/codefixes/fixAwaitInSyncFunction.ts @@ -36,6 +36,10 @@ namespace ts.codefix { function getNodes(sourceFile: SourceFile, start: number): { insertBefore: Node, returnType: TypeNode | undefined } | undefined { const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); const containingFunction = getContainingFunction(token); + if (!containingFunction) { + return; + } + let insertBefore: Node | undefined; switch (containingFunction.kind) { case SyntaxKind.MethodDeclaration: diff --git a/tests/cases/fourslash/codeFixAwaitShouldNotCrashIfNotInFunction.ts b/tests/cases/fourslash/codeFixAwaitShouldNotCrashIfNotInFunction.ts new file mode 100644 index 0000000000000..1ce5c771ed40b --- /dev/null +++ b/tests/cases/fourslash/codeFixAwaitShouldNotCrashIfNotInFunction.ts @@ -0,0 +1,5 @@ +/// + +////await a + +verify.not.codeFixAvailable(); From 8dcbf6961e5ef606ebf49f3959c3b351a01b5a5a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 16 Mar 2018 11:05:33 -0700 Subject: [PATCH 03/13] Fix completions and brace in empty file (#22620) Fixes #22618 --- src/services/completions.ts | 2 +- tests/cases/fourslash/completionAfterBrace.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/completionAfterBrace.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 0d404eb9663bc..a376ad93ffc3f 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1628,7 +1628,7 @@ namespace ts.Completions { } function isFromClassElementDeclaration(node: Node) { - return isClassElement(node.parent) && isClassLike(node.parent.parent); + return node.parent && isClassElement(node.parent) && isClassLike(node.parent.parent); } function isParameterOfConstructorDeclaration(node: Node) { diff --git a/tests/cases/fourslash/completionAfterBrace.ts b/tests/cases/fourslash/completionAfterBrace.ts new file mode 100644 index 0000000000000..ec6cc13689d31 --- /dev/null +++ b/tests/cases/fourslash/completionAfterBrace.ts @@ -0,0 +1,9 @@ +/// + +//// +//// }/**/ +//// + + +goTo.marker(); +verify.not.completionListIsEmpty(); \ No newline at end of file From fc37c8b89c0177755b0fa99e25b9636c845a4da9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 23 Mar 2018 09:42:43 -0700 Subject: [PATCH 04/13] Obtain constraint from destructured property when applicable --- src/compiler/checker.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b5ed4934cac91..e1a759fc81b8b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4083,8 +4083,7 @@ namespace ts { if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) { parentType = getNonNullableType(parentType); } - const propType = getTypeOfPropertyOfType(parentType, text); - const declaredType = propType && getConstraintForLocation(propType, declaration.name); + const declaredType = getConstraintForLocation(getTypeOfPropertyOfType(parentType, text), declaration.name); type = declaredType && getFlowTypeOfReference(declaration, declaredType) || isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) || getIndexTypeOfType(parentType, IndexKind.String); @@ -12408,7 +12407,7 @@ namespace ts { function getTypeOfDestructuredProperty(type: Type, name: PropertyName) { const text = getTextOfPropertyName(name); - return getTypeOfPropertyOfType(type, text) || + return getConstraintForLocation(getTypeOfPropertyOfType(type, text), name) || isNumericLiteralName(text) && getIndexTypeOfType(type, IndexKind.Number) || getIndexTypeOfType(type, IndexKind.String) || unknownType; @@ -13524,7 +13523,7 @@ namespace ts { // and the type of the node includes type variables with constraints that are nullable, we fetch the // apparent type of the node *before* performing control flow analysis such that narrowings apply to // the constraint type. - if (isConstraintPosition(node) && forEachType(type, typeHasNullableConstraint)) { + if (type && isConstraintPosition(node) && forEachType(type, typeHasNullableConstraint)) { return mapType(getWidenedType(type), getBaseConstraintOrType); } return type; From 61f3a829ebfef7ac6fc0f506ad98e113a0432a7c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 23 Mar 2018 09:48:00 -0700 Subject: [PATCH 05/13] Add regression test --- tests/cases/compiler/destructuringWithConstraint.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/cases/compiler/destructuringWithConstraint.ts diff --git a/tests/cases/compiler/destructuringWithConstraint.ts b/tests/cases/compiler/destructuringWithConstraint.ts new file mode 100644 index 0000000000000..505cab86c9767 --- /dev/null +++ b/tests/cases/compiler/destructuringWithConstraint.ts @@ -0,0 +1,12 @@ +// @strict: true + +// Repro from #22823 + +interface Props { + foo?: boolean; +} + +function foo

(props: Readonly

) { + let { foo = false } = props; + if (foo === true) { } +} From b2d702e423ea91ef2297ee6bf609117673d7aa2a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 23 Mar 2018 09:48:11 -0700 Subject: [PATCH 06/13] Accept new baselines --- .../reference/destructuringWithConstraint.js | 20 +++++++++++++ .../destructuringWithConstraint.symbols | 26 +++++++++++++++++ .../destructuringWithConstraint.types | 29 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 tests/baselines/reference/destructuringWithConstraint.js create mode 100644 tests/baselines/reference/destructuringWithConstraint.symbols create mode 100644 tests/baselines/reference/destructuringWithConstraint.types diff --git a/tests/baselines/reference/destructuringWithConstraint.js b/tests/baselines/reference/destructuringWithConstraint.js new file mode 100644 index 0000000000000..2d28971b67893 --- /dev/null +++ b/tests/baselines/reference/destructuringWithConstraint.js @@ -0,0 +1,20 @@ +//// [destructuringWithConstraint.ts] +// Repro from #22823 + +interface Props { + foo?: boolean; +} + +function foo

(props: Readonly

) { + let { foo = false } = props; + if (foo === true) { } +} + + +//// [destructuringWithConstraint.js] +"use strict"; +// Repro from #22823 +function foo(props) { + var _a = props.foo, foo = _a === void 0 ? false : _a; + if (foo === true) { } +} diff --git a/tests/baselines/reference/destructuringWithConstraint.symbols b/tests/baselines/reference/destructuringWithConstraint.symbols new file mode 100644 index 0000000000000..aef7aad768e4e --- /dev/null +++ b/tests/baselines/reference/destructuringWithConstraint.symbols @@ -0,0 +1,26 @@ +=== tests/cases/compiler/destructuringWithConstraint.ts === +// Repro from #22823 + +interface Props { +>Props : Symbol(Props, Decl(destructuringWithConstraint.ts, 0, 0)) + + foo?: boolean; +>foo : Symbol(Props.foo, Decl(destructuringWithConstraint.ts, 2, 17)) +} + +function foo

(props: Readonly

) { +>foo : Symbol(foo, Decl(destructuringWithConstraint.ts, 4, 1)) +>P : Symbol(P, Decl(destructuringWithConstraint.ts, 6, 13)) +>Props : Symbol(Props, Decl(destructuringWithConstraint.ts, 0, 0)) +>props : Symbol(props, Decl(destructuringWithConstraint.ts, 6, 30)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>P : Symbol(P, Decl(destructuringWithConstraint.ts, 6, 13)) + + let { foo = false } = props; +>foo : Symbol(foo, Decl(destructuringWithConstraint.ts, 7, 9)) +>props : Symbol(props, Decl(destructuringWithConstraint.ts, 6, 30)) + + if (foo === true) { } +>foo : Symbol(foo, Decl(destructuringWithConstraint.ts, 7, 9)) +} + diff --git a/tests/baselines/reference/destructuringWithConstraint.types b/tests/baselines/reference/destructuringWithConstraint.types new file mode 100644 index 0000000000000..a58745a6481b2 --- /dev/null +++ b/tests/baselines/reference/destructuringWithConstraint.types @@ -0,0 +1,29 @@ +=== tests/cases/compiler/destructuringWithConstraint.ts === +// Repro from #22823 + +interface Props { +>Props : Props + + foo?: boolean; +>foo : boolean | undefined +} + +function foo

(props: Readonly

) { +>foo :

(props: Readonly

) => void +>P : P +>Props : Props +>props : Readonly

+>Readonly : Readonly +>P : P + + let { foo = false } = props; +>foo : boolean +>false : false +>props : Readonly

+ + if (foo === true) { } +>foo === true : boolean +>foo : boolean +>true : true +} + From b4e83f5c12019e551f463bdf503923739d53e37d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 25 Mar 2018 11:29:58 -0700 Subject: [PATCH 07/13] Add missing type relationship for conditional types --- src/compiler/checker.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e1a759fc81b8b..6e1bc4df603ab 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10231,10 +10231,13 @@ namespace ts { if (result = isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), reportErrors)) { result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), reportErrors); } - if (result) { - errorInfo = saveErrorInfo; - return result; - } + } + else { + result = isRelatedTo(getDefaultConstraintOfConditionalType(source), getDefaultConstraintOfConditionalType(target), reportErrors); + } + if (result) { + errorInfo = saveErrorInfo; + return result; } } else if (relation !== definitelyAssignableRelation) { From 3d04388907f0433dc4d957790520c440f48e33a7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 25 Mar 2018 11:30:08 -0700 Subject: [PATCH 08/13] Add tests --- .../types/conditional/conditionalTypes2.ts | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/cases/conformance/types/conditional/conditionalTypes2.ts diff --git a/tests/cases/conformance/types/conditional/conditionalTypes2.ts b/tests/cases/conformance/types/conditional/conditionalTypes2.ts new file mode 100644 index 0000000000000..d08700a0119f9 --- /dev/null +++ b/tests/cases/conformance/types/conditional/conditionalTypes2.ts @@ -0,0 +1,65 @@ +// @strict: true +// @declaration: true + +interface Covariant { + foo: T extends string ? T : number; +} + +interface Contravariant { + foo: T extends string ? keyof T : number; +} + +interface Invariant { + foo: T extends string ? keyof T : T; +} + +interface A { a: string } +interface B extends A { b: string } + + +function f1(a: Covariant, b: Covariant) { + a = b; + b = a; // Error +} + +function f2(a: Contravariant, b: Contravariant) { + a = b; // Error + b = a; +} + +function f3(a: Invariant, b: Invariant) { + a = b; // Error + b = a; // Error +} + +// Repros from #22860 + +export class Option { + toVector(): Vector { + return undefined; + } +} + +interface Seq { + tail(): Option>; +} + +class Vector implements Seq { + tail(): Option> { + return undefined; + } + partition2(predicate:(v:T)=>v is U): [Vector,Vector>]; + partition2(predicate:(x:T)=>boolean): [Vector,Vector]; + partition2(predicate:(v:T)=>boolean): [Vector,Vector] { + return undefined; + } +} + +interface A1 { + bat: B1>; +} + +interface B1 extends A1 { + bat: B1>; + boom: T extends any ? true : true +} From 7df518d61a246b6617146b23ec2021ce666d2430 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 25 Mar 2018 11:33:24 -0700 Subject: [PATCH 09/13] Add tests --- .../conformance/types/conditional/conditionalTypes2.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/cases/conformance/types/conditional/conditionalTypes2.ts b/tests/cases/conformance/types/conditional/conditionalTypes2.ts index d08700a0119f9..500432bb34c32 100644 --- a/tests/cases/conformance/types/conditional/conditionalTypes2.ts +++ b/tests/cases/conformance/types/conditional/conditionalTypes2.ts @@ -34,18 +34,18 @@ function f3(a: Invariant, b: Invariant) { // Repros from #22860 -export class Option { +class Opt { toVector(): Vector { return undefined; } } interface Seq { - tail(): Option>; + tail(): Opt>; } class Vector implements Seq { - tail(): Option> { + tail(): Opt> { return undefined; } partition2(predicate:(v:T)=>v is U): [Vector,Vector>]; From 79cd7721e96832b6f33295fe26ce2eadc0b99ea4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 25 Mar 2018 11:33:34 -0700 Subject: [PATCH 10/13] Accept new baselines --- .../reference/conditionalTypes2.errors.txt | 90 +++++++ .../baselines/reference/conditionalTypes2.js | 138 +++++++++++ .../reference/conditionalTypes2.symbols | 208 +++++++++++++++++ .../reference/conditionalTypes2.types | 219 ++++++++++++++++++ 4 files changed, 655 insertions(+) create mode 100644 tests/baselines/reference/conditionalTypes2.errors.txt create mode 100644 tests/baselines/reference/conditionalTypes2.js create mode 100644 tests/baselines/reference/conditionalTypes2.symbols create mode 100644 tests/baselines/reference/conditionalTypes2.types diff --git a/tests/baselines/reference/conditionalTypes2.errors.txt b/tests/baselines/reference/conditionalTypes2.errors.txt new file mode 100644 index 0000000000000..8a712d929c49a --- /dev/null +++ b/tests/baselines/reference/conditionalTypes2.errors.txt @@ -0,0 +1,90 @@ +tests/cases/conformance/types/conditional/conditionalTypes2.ts(19,5): error TS2322: Type 'Covariant' is not assignable to type 'Covariant'. + Type 'A' is not assignable to type 'B'. + Property 'b' is missing in type 'A'. +tests/cases/conformance/types/conditional/conditionalTypes2.ts(23,5): error TS2322: Type 'Contravariant' is not assignable to type 'Contravariant'. + Type 'A' is not assignable to type 'B'. +tests/cases/conformance/types/conditional/conditionalTypes2.ts(28,5): error TS2322: Type 'Invariant' is not assignable to type 'Invariant'. + Type 'A' is not assignable to type 'B'. +tests/cases/conformance/types/conditional/conditionalTypes2.ts(29,5): error TS2322: Type 'Invariant' is not assignable to type 'Invariant'. + Types of property 'foo' are incompatible. + Type 'A' is not assignable to type 'B'. + + +==== tests/cases/conformance/types/conditional/conditionalTypes2.ts (4 errors) ==== + interface Covariant { + foo: T extends string ? T : number; + } + + interface Contravariant { + foo: T extends string ? keyof T : number; + } + + interface Invariant { + foo: T extends string ? keyof T : T; + } + + interface A { a: string } + interface B extends A { b: string } + + + function f1(a: Covariant, b: Covariant) { + a = b; + b = a; // Error + ~ +!!! error TS2322: Type 'Covariant' is not assignable to type 'Covariant'. +!!! error TS2322: Type 'A' is not assignable to type 'B'. +!!! error TS2322: Property 'b' is missing in type 'A'. + } + + function f2(a: Contravariant, b: Contravariant) { + a = b; // Error + ~ +!!! error TS2322: Type 'Contravariant' is not assignable to type 'Contravariant'. +!!! error TS2322: Type 'A' is not assignable to type 'B'. + b = a; + } + + function f3(a: Invariant, b: Invariant) { + a = b; // Error + ~ +!!! error TS2322: Type 'Invariant' is not assignable to type 'Invariant'. +!!! error TS2322: Type 'A' is not assignable to type 'B'. + b = a; // Error + ~ +!!! error TS2322: Type 'Invariant' is not assignable to type 'Invariant'. +!!! error TS2322: Types of property 'foo' are incompatible. +!!! error TS2322: Type 'A' is not assignable to type 'B'. + } + + // Repros from #22860 + + class Opt { + toVector(): Vector { + return undefined; + } + } + + interface Seq { + tail(): Opt>; + } + + class Vector implements Seq { + tail(): Opt> { + return undefined; + } + partition2(predicate:(v:T)=>v is U): [Vector,Vector>]; + partition2(predicate:(x:T)=>boolean): [Vector,Vector]; + partition2(predicate:(v:T)=>boolean): [Vector,Vector] { + return undefined; + } + } + + interface A1 { + bat: B1>; + } + + interface B1 extends A1 { + bat: B1>; + boom: T extends any ? true : true + } + \ No newline at end of file diff --git a/tests/baselines/reference/conditionalTypes2.js b/tests/baselines/reference/conditionalTypes2.js new file mode 100644 index 0000000000000..ecfec329439f6 --- /dev/null +++ b/tests/baselines/reference/conditionalTypes2.js @@ -0,0 +1,138 @@ +//// [conditionalTypes2.ts] +interface Covariant { + foo: T extends string ? T : number; +} + +interface Contravariant { + foo: T extends string ? keyof T : number; +} + +interface Invariant { + foo: T extends string ? keyof T : T; +} + +interface A { a: string } +interface B extends A { b: string } + + +function f1(a: Covariant, b: Covariant) { + a = b; + b = a; // Error +} + +function f2(a: Contravariant, b: Contravariant) { + a = b; // Error + b = a; +} + +function f3(a: Invariant, b: Invariant) { + a = b; // Error + b = a; // Error +} + +// Repros from #22860 + +class Opt { + toVector(): Vector { + return undefined; + } +} + +interface Seq { + tail(): Opt>; +} + +class Vector implements Seq { + tail(): Opt> { + return undefined; + } + partition2(predicate:(v:T)=>v is U): [Vector,Vector>]; + partition2(predicate:(x:T)=>boolean): [Vector,Vector]; + partition2(predicate:(v:T)=>boolean): [Vector,Vector] { + return undefined; + } +} + +interface A1 { + bat: B1>; +} + +interface B1 extends A1 { + bat: B1>; + boom: T extends any ? true : true +} + + +//// [conditionalTypes2.js] +"use strict"; +function f1(a, b) { + a = b; + b = a; // Error +} +function f2(a, b) { + a = b; // Error + b = a; +} +function f3(a, b) { + a = b; // Error + b = a; // Error +} +// Repros from #22860 +var Opt = /** @class */ (function () { + function Opt() { + } + Opt.prototype.toVector = function () { + return undefined; + }; + return Opt; +}()); +var Vector = /** @class */ (function () { + function Vector() { + } + Vector.prototype.tail = function () { + return undefined; + }; + Vector.prototype.partition2 = function (predicate) { + return undefined; + }; + return Vector; +}()); + + +//// [conditionalTypes2.d.ts] +interface Covariant { + foo: T extends string ? T : number; +} +interface Contravariant { + foo: T extends string ? keyof T : number; +} +interface Invariant { + foo: T extends string ? keyof T : T; +} +interface A { + a: string; +} +interface B extends A { + b: string; +} +declare function f1(a: Covariant, b: Covariant): void; +declare function f2(a: Contravariant, b: Contravariant): void; +declare function f3(a: Invariant, b: Invariant): void; +declare class Opt { + toVector(): Vector; +} +interface Seq { + tail(): Opt>; +} +declare class Vector implements Seq { + tail(): Opt>; + partition2(predicate: (v: T) => v is U): [Vector, Vector>]; + partition2(predicate: (x: T) => boolean): [Vector, Vector]; +} +interface A1 { + bat: B1>; +} +interface B1 extends A1 { + bat: B1>; + boom: T extends any ? true : true; +} diff --git a/tests/baselines/reference/conditionalTypes2.symbols b/tests/baselines/reference/conditionalTypes2.symbols new file mode 100644 index 0000000000000..96f7e681255e6 --- /dev/null +++ b/tests/baselines/reference/conditionalTypes2.symbols @@ -0,0 +1,208 @@ +=== tests/cases/conformance/types/conditional/conditionalTypes2.ts === +interface Covariant { +>Covariant : Symbol(Covariant, Decl(conditionalTypes2.ts, 0, 0)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 0, 20)) + + foo: T extends string ? T : number; +>foo : Symbol(Covariant.foo, Decl(conditionalTypes2.ts, 0, 24)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 0, 20)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 0, 20)) +} + +interface Contravariant { +>Contravariant : Symbol(Contravariant, Decl(conditionalTypes2.ts, 2, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 4, 24)) + + foo: T extends string ? keyof T : number; +>foo : Symbol(Contravariant.foo, Decl(conditionalTypes2.ts, 4, 28)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 4, 24)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 4, 24)) +} + +interface Invariant { +>Invariant : Symbol(Invariant, Decl(conditionalTypes2.ts, 6, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 8, 20)) + + foo: T extends string ? keyof T : T; +>foo : Symbol(Invariant.foo, Decl(conditionalTypes2.ts, 8, 24)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 8, 20)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 8, 20)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 8, 20)) +} + +interface A { a: string } +>A : Symbol(A, Decl(conditionalTypes2.ts, 10, 1)) +>a : Symbol(A.a, Decl(conditionalTypes2.ts, 12, 13)) + +interface B extends A { b: string } +>B : Symbol(B, Decl(conditionalTypes2.ts, 12, 25)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 10, 1)) +>b : Symbol(B.b, Decl(conditionalTypes2.ts, 13, 23)) + + +function f1(a: Covariant, b: Covariant) { +>f1 : Symbol(f1, Decl(conditionalTypes2.ts, 13, 35)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 16, 12)) +>Covariant : Symbol(Covariant, Decl(conditionalTypes2.ts, 0, 0)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 10, 1)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 16, 28)) +>Covariant : Symbol(Covariant, Decl(conditionalTypes2.ts, 0, 0)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 12, 25)) + + a = b; +>a : Symbol(a, Decl(conditionalTypes2.ts, 16, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 16, 28)) + + b = a; // Error +>b : Symbol(b, Decl(conditionalTypes2.ts, 16, 28)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 16, 12)) +} + +function f2(a: Contravariant, b: Contravariant) { +>f2 : Symbol(f2, Decl(conditionalTypes2.ts, 19, 1)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 21, 12)) +>Contravariant : Symbol(Contravariant, Decl(conditionalTypes2.ts, 2, 1)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 10, 1)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 21, 32)) +>Contravariant : Symbol(Contravariant, Decl(conditionalTypes2.ts, 2, 1)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 12, 25)) + + a = b; // Error +>a : Symbol(a, Decl(conditionalTypes2.ts, 21, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 21, 32)) + + b = a; +>b : Symbol(b, Decl(conditionalTypes2.ts, 21, 32)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 21, 12)) +} + +function f3(a: Invariant, b: Invariant) { +>f3 : Symbol(f3, Decl(conditionalTypes2.ts, 24, 1)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 26, 12)) +>Invariant : Symbol(Invariant, Decl(conditionalTypes2.ts, 6, 1)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 10, 1)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 26, 28)) +>Invariant : Symbol(Invariant, Decl(conditionalTypes2.ts, 6, 1)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 12, 25)) + + a = b; // Error +>a : Symbol(a, Decl(conditionalTypes2.ts, 26, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 26, 28)) + + b = a; // Error +>b : Symbol(b, Decl(conditionalTypes2.ts, 26, 28)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 26, 12)) +} + +// Repros from #22860 + +class Opt { +>Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 29, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 33, 10)) + + toVector(): Vector { +>toVector : Symbol(Opt.toVector, Decl(conditionalTypes2.ts, 33, 14)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 33, 10)) + + return undefined; +>undefined : Symbol(undefined) + } +} + +interface Seq { +>Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 37, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 14)) + + tail(): Opt>; +>tail : Symbol(Seq.tail, Decl(conditionalTypes2.ts, 39, 18)) +>Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 29, 1)) +>Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 37, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 14)) +} + +class Vector implements Seq { +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 37, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) + + tail(): Opt> { +>tail : Symbol(Vector.tail, Decl(conditionalTypes2.ts, 43, 35)) +>Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 29, 1)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) + + return undefined; +>undefined : Symbol(undefined) + } + partition2(predicate:(v:T)=>v is U): [Vector,Vector>]; +>partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 46, 5), Decl(conditionalTypes2.ts, 47, 88), Decl(conditionalTypes2.ts, 48, 64)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 47, 15)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 47, 28)) +>v : Symbol(v, Decl(conditionalTypes2.ts, 47, 39)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>v : Symbol(v, Decl(conditionalTypes2.ts, 47, 39)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 47, 15)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 47, 15)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) +>Exclude : Symbol(Exclude, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 47, 15)) + + partition2(predicate:(x:T)=>boolean): [Vector,Vector]; +>partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 46, 5), Decl(conditionalTypes2.ts, 47, 88), Decl(conditionalTypes2.ts, 48, 64)) +>predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 48, 15)) +>x : Symbol(x, Decl(conditionalTypes2.ts, 48, 26)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) + + partition2(predicate:(v:T)=>boolean): [Vector,Vector] { +>partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 46, 5), Decl(conditionalTypes2.ts, 47, 88), Decl(conditionalTypes2.ts, 48, 64)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 49, 15)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 49, 28)) +>v : Symbol(v, Decl(conditionalTypes2.ts, 49, 39)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 49, 15)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) + + return undefined; +>undefined : Symbol(undefined) + } +} + +interface A1 { +>A1 : Symbol(A1, Decl(conditionalTypes2.ts, 52, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13)) + + bat: B1>; +>bat : Symbol(A1.bat, Decl(conditionalTypes2.ts, 54, 17)) +>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 56, 1)) +>A1 : Symbol(A1, Decl(conditionalTypes2.ts, 52, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13)) +} + +interface B1 extends A1 { +>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 56, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 58, 13)) +>A1 : Symbol(A1, Decl(conditionalTypes2.ts, 52, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 58, 13)) + + bat: B1>; +>bat : Symbol(B1.bat, Decl(conditionalTypes2.ts, 58, 31)) +>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 56, 1)) +>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 56, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 58, 13)) + + boom: T extends any ? true : true +>boom : Symbol(B1.boom, Decl(conditionalTypes2.ts, 59, 19)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 58, 13)) +} + diff --git a/tests/baselines/reference/conditionalTypes2.types b/tests/baselines/reference/conditionalTypes2.types new file mode 100644 index 0000000000000..a31a63524756b --- /dev/null +++ b/tests/baselines/reference/conditionalTypes2.types @@ -0,0 +1,219 @@ +=== tests/cases/conformance/types/conditional/conditionalTypes2.ts === +interface Covariant { +>Covariant : Covariant +>T : T + + foo: T extends string ? T : number; +>foo : T extends string ? T : number +>T : T +>T : T +} + +interface Contravariant { +>Contravariant : Contravariant +>T : T + + foo: T extends string ? keyof T : number; +>foo : T extends string ? keyof T : number +>T : T +>T : T +} + +interface Invariant { +>Invariant : Invariant +>T : T + + foo: T extends string ? keyof T : T; +>foo : T extends string ? keyof T : T +>T : T +>T : T +>T : T +} + +interface A { a: string } +>A : A +>a : string + +interface B extends A { b: string } +>B : B +>A : A +>b : string + + +function f1(a: Covariant, b: Covariant) { +>f1 : (a: Covariant, b: Covariant) => void +>a : Covariant +>Covariant : Covariant +>A : A +>b : Covariant +>Covariant : Covariant +>B : B + + a = b; +>a = b : Covariant +>a : Covariant +>b : Covariant + + b = a; // Error +>b = a : Covariant +>b : Covariant +>a : Covariant +} + +function f2(a: Contravariant, b: Contravariant) { +>f2 : (a: Contravariant, b: Contravariant) => void +>a : Contravariant +>Contravariant : Contravariant +>A : A +>b : Contravariant +>Contravariant : Contravariant +>B : B + + a = b; // Error +>a = b : Contravariant +>a : Contravariant +>b : Contravariant + + b = a; +>b = a : Contravariant +>b : Contravariant +>a : Contravariant +} + +function f3(a: Invariant, b: Invariant) { +>f3 : (a: Invariant, b: Invariant) => void +>a : Invariant +>Invariant : Invariant +>A : A +>b : Invariant +>Invariant : Invariant +>B : B + + a = b; // Error +>a = b : Invariant +>a : Invariant +>b : Invariant + + b = a; // Error +>b = a : Invariant +>b : Invariant +>a : Invariant +} + +// Repros from #22860 + +class Opt { +>Opt : Opt +>T : T + + toVector(): Vector { +>toVector : () => Vector +>Vector : Vector +>T : T + + return undefined; +>undefined : any +>undefined : undefined + } +} + +interface Seq { +>Seq : Seq +>T : T + + tail(): Opt>; +>tail : () => Opt> +>Opt : Opt +>Seq : Seq +>T : T +} + +class Vector implements Seq { +>Vector : Vector +>T : T +>Seq : Seq +>T : T + + tail(): Opt> { +>tail : () => Opt> +>Opt : Opt +>Vector : Vector +>T : T + + return undefined; +>undefined : any +>undefined : undefined + } + partition2(predicate:(v:T)=>v is U): [Vector,Vector>]; +>partition2 : { (predicate: (v: T) => v is U): [Vector, Vector>]; (predicate: (x: T) => boolean): [Vector, Vector]; } +>U : U +>T : T +>predicate : (v: T) => v is U +>v : T +>T : T +>v : any +>U : U +>Vector : Vector +>U : U +>Vector : Vector +>Exclude : Exclude +>T : T +>U : U + + partition2(predicate:(x:T)=>boolean): [Vector,Vector]; +>partition2 : { (predicate: (v: T) => v is U): [Vector, Vector>]; (predicate: (x: T) => boolean): [Vector, Vector]; } +>predicate : (x: T) => boolean +>x : T +>T : T +>Vector : Vector +>T : T +>Vector : Vector +>T : T + + partition2(predicate:(v:T)=>boolean): [Vector,Vector] { +>partition2 : { (predicate: (v: T) => v is U): [Vector, Vector>]; (predicate: (x: T) => boolean): [Vector, Vector]; } +>U : U +>T : T +>predicate : (v: T) => boolean +>v : T +>T : T +>Vector : Vector +>U : U +>Vector : Vector + + return undefined; +>undefined : any +>undefined : undefined + } +} + +interface A1 { +>A1 : A1 +>T : T + + bat: B1>; +>bat : B1> +>B1 : B1 +>A1 : A1 +>T : T +} + +interface B1 extends A1 { +>B1 : B1 +>T : T +>A1 : A1 +>T : T + + bat: B1>; +>bat : B1> +>B1 : B1 +>B1 : B1 +>T : T + + boom: T extends any ? true : true +>boom : T extends any ? true : true +>T : T +>true : true +>true : true +} + From ca3d0d37a7d58692a6daadb2fe6b5dc338cf63e8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 25 Mar 2018 15:24:31 -0700 Subject: [PATCH 11/13] Change to more conservative conditional type relationship --- src/compiler/checker.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6e1bc4df603ab..62ca22845f313 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10226,18 +10226,18 @@ namespace ts { } else if (source.flags & TypeFlags.Conditional) { if (target.flags & TypeFlags.Conditional) { - if (isTypeIdenticalTo((source).checkType, (target).checkType) && - isTypeIdenticalTo((source).extendsType, (target).extendsType)) { + // Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if + // one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2, + // and Y1 is related to Y2. + if (isTypeIdenticalTo((source).extendsType, (target).extendsType) && + (isRelatedTo((source).checkType, (target).checkType) || isRelatedTo((target).checkType, (source).checkType))) { if (result = isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), reportErrors)) { result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), reportErrors); } - } - else { - result = isRelatedTo(getDefaultConstraintOfConditionalType(source), getDefaultConstraintOfConditionalType(target), reportErrors); - } - if (result) { - errorInfo = saveErrorInfo; - return result; + if (result) { + errorInfo = saveErrorInfo; + return result; + } } } else if (relation !== definitelyAssignableRelation) { From 072401e29fd3db0fcf860707e1a2cf4e673c75d2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 25 Mar 2018 15:30:46 -0700 Subject: [PATCH 12/13] Change test to use type variables --- .../conformance/types/conditional/conditionalTypes2.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/cases/conformance/types/conditional/conditionalTypes2.ts b/tests/cases/conformance/types/conditional/conditionalTypes2.ts index 500432bb34c32..5ba189236b05b 100644 --- a/tests/cases/conformance/types/conditional/conditionalTypes2.ts +++ b/tests/cases/conformance/types/conditional/conditionalTypes2.ts @@ -13,21 +13,17 @@ interface Invariant { foo: T extends string ? keyof T : T; } -interface A { a: string } -interface B extends A { b: string } - - -function f1(a: Covariant, b: Covariant) { +function f1(a: Covariant, b: Covariant) { a = b; b = a; // Error } -function f2(a: Contravariant, b: Contravariant) { +function f2(a: Contravariant, b: Contravariant) { a = b; // Error b = a; } -function f3(a: Invariant, b: Invariant) { +function f3(a: Invariant, b: Invariant) { a = b; // Error b = a; // Error } From ae8413e9ed0dc227c673a1d0b9a6cd9b635cc504 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 25 Mar 2018 15:32:06 -0700 Subject: [PATCH 13/13] Accept new baselines --- .../reference/conditionalTypes2.errors.txt | 34 +-- .../baselines/reference/conditionalTypes2.js | 22 +- .../reference/conditionalTypes2.symbols | 209 +++++++++--------- .../reference/conditionalTypes2.types | 25 +-- 4 files changed, 139 insertions(+), 151 deletions(-) diff --git a/tests/baselines/reference/conditionalTypes2.errors.txt b/tests/baselines/reference/conditionalTypes2.errors.txt index 8a712d929c49a..a41522102682f 100644 --- a/tests/baselines/reference/conditionalTypes2.errors.txt +++ b/tests/baselines/reference/conditionalTypes2.errors.txt @@ -1,13 +1,15 @@ -tests/cases/conformance/types/conditional/conditionalTypes2.ts(19,5): error TS2322: Type 'Covariant' is not assignable to type 'Covariant'. +tests/cases/conformance/types/conditional/conditionalTypes2.ts(15,5): error TS2322: Type 'Covariant' is not assignable to type 'Covariant'. Type 'A' is not assignable to type 'B'. - Property 'b' is missing in type 'A'. -tests/cases/conformance/types/conditional/conditionalTypes2.ts(23,5): error TS2322: Type 'Contravariant' is not assignable to type 'Contravariant'. +tests/cases/conformance/types/conditional/conditionalTypes2.ts(19,5): error TS2322: Type 'Contravariant' is not assignable to type 'Contravariant'. Type 'A' is not assignable to type 'B'. -tests/cases/conformance/types/conditional/conditionalTypes2.ts(28,5): error TS2322: Type 'Invariant' is not assignable to type 'Invariant'. - Type 'A' is not assignable to type 'B'. -tests/cases/conformance/types/conditional/conditionalTypes2.ts(29,5): error TS2322: Type 'Invariant' is not assignable to type 'Invariant'. +tests/cases/conformance/types/conditional/conditionalTypes2.ts(24,5): error TS2322: Type 'Invariant' is not assignable to type 'Invariant'. + Types of property 'foo' are incompatible. + Type 'B extends string ? keyof B : B' is not assignable to type 'A extends string ? keyof A : A'. + Type 'keyof B' is not assignable to type 'keyof A'. +tests/cases/conformance/types/conditional/conditionalTypes2.ts(25,5): error TS2322: Type 'Invariant' is not assignable to type 'Invariant'. Types of property 'foo' are incompatible. - Type 'A' is not assignable to type 'B'. + Type 'A extends string ? keyof A : A' is not assignable to type 'B extends string ? keyof B : B'. + Type 'A' is not assignable to type 'B'. ==== tests/cases/conformance/types/conditional/conditionalTypes2.ts (4 errors) ==== @@ -23,20 +25,15 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(29,5): error TS23 foo: T extends string ? keyof T : T; } - interface A { a: string } - interface B extends A { b: string } - - - function f1(a: Covariant, b: Covariant) { + function f1(a: Covariant, b: Covariant) { a = b; b = a; // Error ~ !!! error TS2322: Type 'Covariant' is not assignable to type 'Covariant'. !!! error TS2322: Type 'A' is not assignable to type 'B'. -!!! error TS2322: Property 'b' is missing in type 'A'. } - function f2(a: Contravariant, b: Contravariant) { + function f2(a: Contravariant, b: Contravariant) { a = b; // Error ~ !!! error TS2322: Type 'Contravariant' is not assignable to type 'Contravariant'. @@ -44,16 +41,19 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(29,5): error TS23 b = a; } - function f3(a: Invariant, b: Invariant) { + function f3(a: Invariant, b: Invariant) { a = b; // Error ~ !!! error TS2322: Type 'Invariant' is not assignable to type 'Invariant'. -!!! error TS2322: Type 'A' is not assignable to type 'B'. +!!! error TS2322: Types of property 'foo' are incompatible. +!!! error TS2322: Type 'B extends string ? keyof B : B' is not assignable to type 'A extends string ? keyof A : A'. +!!! error TS2322: Type 'keyof B' is not assignable to type 'keyof A'. b = a; // Error ~ !!! error TS2322: Type 'Invariant' is not assignable to type 'Invariant'. !!! error TS2322: Types of property 'foo' are incompatible. -!!! error TS2322: Type 'A' is not assignable to type 'B'. +!!! error TS2322: Type 'A extends string ? keyof A : A' is not assignable to type 'B extends string ? keyof B : B'. +!!! error TS2322: Type 'A' is not assignable to type 'B'. } // Repros from #22860 diff --git a/tests/baselines/reference/conditionalTypes2.js b/tests/baselines/reference/conditionalTypes2.js index ecfec329439f6..5193bae3345d3 100644 --- a/tests/baselines/reference/conditionalTypes2.js +++ b/tests/baselines/reference/conditionalTypes2.js @@ -11,21 +11,17 @@ interface Invariant { foo: T extends string ? keyof T : T; } -interface A { a: string } -interface B extends A { b: string } - - -function f1(a: Covariant, b: Covariant) { +function f1(a: Covariant, b: Covariant) { a = b; b = a; // Error } -function f2(a: Contravariant, b: Contravariant) { +function f2(a: Contravariant, b: Contravariant) { a = b; // Error b = a; } -function f3(a: Invariant, b: Invariant) { +function f3(a: Invariant, b: Invariant) { a = b; // Error b = a; // Error } @@ -109,15 +105,9 @@ interface Contravariant { interface Invariant { foo: T extends string ? keyof T : T; } -interface A { - a: string; -} -interface B extends A { - b: string; -} -declare function f1(a: Covariant, b: Covariant): void; -declare function f2(a: Contravariant, b: Contravariant): void; -declare function f3(a: Invariant, b: Invariant): void; +declare function f1(a: Covariant, b: Covariant): void; +declare function f2(a: Contravariant, b: Contravariant): void; +declare function f3(a: Invariant, b: Invariant): void; declare class Opt { toVector(): Vector; } diff --git a/tests/baselines/reference/conditionalTypes2.symbols b/tests/baselines/reference/conditionalTypes2.symbols index 96f7e681255e6..4d9cd27238be5 100644 --- a/tests/baselines/reference/conditionalTypes2.symbols +++ b/tests/baselines/reference/conditionalTypes2.symbols @@ -30,80 +30,79 @@ interface Invariant { >T : Symbol(T, Decl(conditionalTypes2.ts, 8, 20)) } -interface A { a: string } ->A : Symbol(A, Decl(conditionalTypes2.ts, 10, 1)) ->a : Symbol(A.a, Decl(conditionalTypes2.ts, 12, 13)) - -interface B extends A { b: string } ->B : Symbol(B, Decl(conditionalTypes2.ts, 12, 25)) ->A : Symbol(A, Decl(conditionalTypes2.ts, 10, 1)) ->b : Symbol(B.b, Decl(conditionalTypes2.ts, 13, 23)) - - -function f1(a: Covariant, b: Covariant) { ->f1 : Symbol(f1, Decl(conditionalTypes2.ts, 13, 35)) ->a : Symbol(a, Decl(conditionalTypes2.ts, 16, 12)) +function f1(a: Covariant, b: Covariant) { +>f1 : Symbol(f1, Decl(conditionalTypes2.ts, 10, 1)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 12, 12)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 12, 14)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 12, 12)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 12, 28)) >Covariant : Symbol(Covariant, Decl(conditionalTypes2.ts, 0, 0)) ->A : Symbol(A, Decl(conditionalTypes2.ts, 10, 1)) ->b : Symbol(b, Decl(conditionalTypes2.ts, 16, 28)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 12, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 12, 44)) >Covariant : Symbol(Covariant, Decl(conditionalTypes2.ts, 0, 0)) ->B : Symbol(B, Decl(conditionalTypes2.ts, 12, 25)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 12, 14)) a = b; ->a : Symbol(a, Decl(conditionalTypes2.ts, 16, 12)) ->b : Symbol(b, Decl(conditionalTypes2.ts, 16, 28)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 12, 28)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 12, 44)) b = a; // Error ->b : Symbol(b, Decl(conditionalTypes2.ts, 16, 28)) ->a : Symbol(a, Decl(conditionalTypes2.ts, 16, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 12, 44)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 12, 28)) } -function f2(a: Contravariant, b: Contravariant) { ->f2 : Symbol(f2, Decl(conditionalTypes2.ts, 19, 1)) ->a : Symbol(a, Decl(conditionalTypes2.ts, 21, 12)) +function f2(a: Contravariant, b: Contravariant) { +>f2 : Symbol(f2, Decl(conditionalTypes2.ts, 15, 1)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 17, 12)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 17, 14)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 17, 12)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 17, 28)) >Contravariant : Symbol(Contravariant, Decl(conditionalTypes2.ts, 2, 1)) ->A : Symbol(A, Decl(conditionalTypes2.ts, 10, 1)) ->b : Symbol(b, Decl(conditionalTypes2.ts, 21, 32)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 17, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 17, 48)) >Contravariant : Symbol(Contravariant, Decl(conditionalTypes2.ts, 2, 1)) ->B : Symbol(B, Decl(conditionalTypes2.ts, 12, 25)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 17, 14)) a = b; // Error ->a : Symbol(a, Decl(conditionalTypes2.ts, 21, 12)) ->b : Symbol(b, Decl(conditionalTypes2.ts, 21, 32)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 17, 28)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 17, 48)) b = a; ->b : Symbol(b, Decl(conditionalTypes2.ts, 21, 32)) ->a : Symbol(a, Decl(conditionalTypes2.ts, 21, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 17, 48)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 17, 28)) } -function f3(a: Invariant, b: Invariant) { ->f3 : Symbol(f3, Decl(conditionalTypes2.ts, 24, 1)) ->a : Symbol(a, Decl(conditionalTypes2.ts, 26, 12)) +function f3(a: Invariant, b: Invariant) { +>f3 : Symbol(f3, Decl(conditionalTypes2.ts, 20, 1)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 22, 12)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 22, 14)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 22, 12)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 22, 28)) >Invariant : Symbol(Invariant, Decl(conditionalTypes2.ts, 6, 1)) ->A : Symbol(A, Decl(conditionalTypes2.ts, 10, 1)) ->b : Symbol(b, Decl(conditionalTypes2.ts, 26, 28)) +>A : Symbol(A, Decl(conditionalTypes2.ts, 22, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 22, 44)) >Invariant : Symbol(Invariant, Decl(conditionalTypes2.ts, 6, 1)) ->B : Symbol(B, Decl(conditionalTypes2.ts, 12, 25)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 22, 14)) a = b; // Error ->a : Symbol(a, Decl(conditionalTypes2.ts, 26, 12)) ->b : Symbol(b, Decl(conditionalTypes2.ts, 26, 28)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 22, 28)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 22, 44)) b = a; // Error ->b : Symbol(b, Decl(conditionalTypes2.ts, 26, 28)) ->a : Symbol(a, Decl(conditionalTypes2.ts, 26, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 22, 44)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 22, 28)) } // Repros from #22860 class Opt { ->Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 29, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 33, 10)) +>Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 25, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 29, 10)) toVector(): Vector { ->toVector : Symbol(Opt.toVector, Decl(conditionalTypes2.ts, 33, 14)) ->Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 33, 10)) +>toVector : Symbol(Opt.toVector, Decl(conditionalTypes2.ts, 29, 14)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 29, 10)) return undefined; >undefined : Symbol(undefined) @@ -111,67 +110,67 @@ class Opt { } interface Seq { ->Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 37, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 39, 14)) +>Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 33, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 35, 14)) tail(): Opt>; ->tail : Symbol(Seq.tail, Decl(conditionalTypes2.ts, 39, 18)) ->Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 29, 1)) ->Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 37, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 39, 14)) +>tail : Symbol(Seq.tail, Decl(conditionalTypes2.ts, 35, 18)) +>Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 25, 1)) +>Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 33, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 35, 14)) } class Vector implements Seq { ->Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) ->Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 37, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) +>Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 33, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) tail(): Opt> { ->tail : Symbol(Vector.tail, Decl(conditionalTypes2.ts, 43, 35)) ->Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 29, 1)) ->Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>tail : Symbol(Vector.tail, Decl(conditionalTypes2.ts, 39, 35)) +>Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 25, 1)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) return undefined; >undefined : Symbol(undefined) } partition2(predicate:(v:T)=>v is U): [Vector,Vector>]; ->partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 46, 5), Decl(conditionalTypes2.ts, 47, 88), Decl(conditionalTypes2.ts, 48, 64)) ->U : Symbol(U, Decl(conditionalTypes2.ts, 47, 15)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) ->predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 47, 28)) ->v : Symbol(v, Decl(conditionalTypes2.ts, 47, 39)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) ->v : Symbol(v, Decl(conditionalTypes2.ts, 47, 39)) ->U : Symbol(U, Decl(conditionalTypes2.ts, 47, 15)) ->Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) ->U : Symbol(U, Decl(conditionalTypes2.ts, 47, 15)) ->Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) +>partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 42, 5), Decl(conditionalTypes2.ts, 43, 88), Decl(conditionalTypes2.ts, 44, 64)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 43, 15)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) +>predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 43, 28)) +>v : Symbol(v, Decl(conditionalTypes2.ts, 43, 39)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) +>v : Symbol(v, Decl(conditionalTypes2.ts, 43, 39)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 43, 15)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 43, 15)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1)) >Exclude : Symbol(Exclude, Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) ->U : Symbol(U, Decl(conditionalTypes2.ts, 47, 15)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 43, 15)) partition2(predicate:(x:T)=>boolean): [Vector,Vector]; ->partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 46, 5), Decl(conditionalTypes2.ts, 47, 88), Decl(conditionalTypes2.ts, 48, 64)) ->predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 48, 15)) ->x : Symbol(x, Decl(conditionalTypes2.ts, 48, 26)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) ->Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) ->Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) +>partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 42, 5), Decl(conditionalTypes2.ts, 43, 88), Decl(conditionalTypes2.ts, 44, 64)) +>predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 44, 15)) +>x : Symbol(x, Decl(conditionalTypes2.ts, 44, 26)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) partition2(predicate:(v:T)=>boolean): [Vector,Vector] { ->partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 46, 5), Decl(conditionalTypes2.ts, 47, 88), Decl(conditionalTypes2.ts, 48, 64)) ->U : Symbol(U, Decl(conditionalTypes2.ts, 49, 15)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) ->predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 49, 28)) ->v : Symbol(v, Decl(conditionalTypes2.ts, 49, 39)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 43, 13)) ->Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) ->U : Symbol(U, Decl(conditionalTypes2.ts, 49, 15)) ->Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 41, 1)) +>partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 42, 5), Decl(conditionalTypes2.ts, 43, 88), Decl(conditionalTypes2.ts, 44, 64)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 45, 15)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) +>predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 45, 28)) +>v : Symbol(v, Decl(conditionalTypes2.ts, 45, 39)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 45, 15)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1)) return undefined; >undefined : Symbol(undefined) @@ -179,30 +178,30 @@ class Vector implements Seq { } interface A1 { ->A1 : Symbol(A1, Decl(conditionalTypes2.ts, 52, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13)) +>A1 : Symbol(A1, Decl(conditionalTypes2.ts, 48, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 50, 13)) bat: B1>; ->bat : Symbol(A1.bat, Decl(conditionalTypes2.ts, 54, 17)) ->B1 : Symbol(B1, Decl(conditionalTypes2.ts, 56, 1)) ->A1 : Symbol(A1, Decl(conditionalTypes2.ts, 52, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13)) +>bat : Symbol(A1.bat, Decl(conditionalTypes2.ts, 50, 17)) +>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 52, 1)) +>A1 : Symbol(A1, Decl(conditionalTypes2.ts, 48, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 50, 13)) } interface B1 extends A1 { ->B1 : Symbol(B1, Decl(conditionalTypes2.ts, 56, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 58, 13)) ->A1 : Symbol(A1, Decl(conditionalTypes2.ts, 52, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 58, 13)) +>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 52, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13)) +>A1 : Symbol(A1, Decl(conditionalTypes2.ts, 48, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13)) bat: B1>; ->bat : Symbol(B1.bat, Decl(conditionalTypes2.ts, 58, 31)) ->B1 : Symbol(B1, Decl(conditionalTypes2.ts, 56, 1)) ->B1 : Symbol(B1, Decl(conditionalTypes2.ts, 56, 1)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 58, 13)) +>bat : Symbol(B1.bat, Decl(conditionalTypes2.ts, 54, 31)) +>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 52, 1)) +>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 52, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13)) boom: T extends any ? true : true ->boom : Symbol(B1.boom, Decl(conditionalTypes2.ts, 59, 19)) ->T : Symbol(T, Decl(conditionalTypes2.ts, 58, 13)) +>boom : Symbol(B1.boom, Decl(conditionalTypes2.ts, 55, 19)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13)) } diff --git a/tests/baselines/reference/conditionalTypes2.types b/tests/baselines/reference/conditionalTypes2.types index a31a63524756b..e3dad1fc280e5 100644 --- a/tests/baselines/reference/conditionalTypes2.types +++ b/tests/baselines/reference/conditionalTypes2.types @@ -30,18 +30,11 @@ interface Invariant { >T : T } -interface A { a: string } +function f1(a: Covariant, b: Covariant) { +>f1 : (a: Covariant, b: Covariant) => void >A : A ->a : string - -interface B extends A { b: string } >B : B >A : A ->b : string - - -function f1(a: Covariant, b: Covariant) { ->f1 : (a: Covariant, b: Covariant) => void >a : Covariant >Covariant : Covariant >A : A @@ -60,8 +53,11 @@ function f1(a: Covariant, b: Covariant) { >a : Covariant } -function f2(a: Contravariant, b: Contravariant) { ->f2 : (a: Contravariant, b: Contravariant) => void +function f2(a: Contravariant, b: Contravariant) { +>f2 : (a: Contravariant, b: Contravariant) => void +>A : A +>B : B +>A : A >a : Contravariant >Contravariant : Contravariant >A : A @@ -80,8 +76,11 @@ function f2(a: Contravariant, b: Contravariant) { >a : Contravariant } -function f3(a: Invariant, b: Invariant) { ->f3 : (a: Invariant, b: Invariant) => void +function f3(a: Invariant, b: Invariant) { +>f3 : (a: Invariant, b: Invariant) => void +>A : A +>B : B +>A : A >a : Invariant >Invariant : Invariant >A : A