diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b5ed4934cac91..62ca22845f313 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); @@ -10227,8 +10226,11 @@ 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); } @@ -12408,7 +12410,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 +13526,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; 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/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; } 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/baselines/reference/conditionalTypes2.errors.txt b/tests/baselines/reference/conditionalTypes2.errors.txt new file mode 100644 index 0000000000000..a41522102682f --- /dev/null +++ b/tests/baselines/reference/conditionalTypes2.errors.txt @@ -0,0 +1,90 @@ +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'. +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(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 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) ==== + 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; + } + + 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'. + } + + 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: 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 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 + + 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..5193bae3345d3 --- /dev/null +++ b/tests/baselines/reference/conditionalTypes2.js @@ -0,0 +1,128 @@ +//// [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; +} + +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; +} +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..4d9cd27238be5 --- /dev/null +++ b/tests/baselines/reference/conditionalTypes2.symbols @@ -0,0 +1,207 @@ +=== 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)) +} + +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, 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, 14)) + + a = b; +>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, 12, 44)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 12, 28)) +} + +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, 17, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 17, 48)) +>Contravariant : Symbol(Contravariant, Decl(conditionalTypes2.ts, 2, 1)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 17, 14)) + + a = b; // Error +>a : Symbol(a, Decl(conditionalTypes2.ts, 17, 28)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 17, 48)) + + b = a; +>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, 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, 22, 12)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 22, 44)) +>Invariant : Symbol(Invariant, Decl(conditionalTypes2.ts, 6, 1)) +>B : Symbol(B, Decl(conditionalTypes2.ts, 22, 14)) + + a = b; // Error +>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, 22, 44)) +>a : Symbol(a, Decl(conditionalTypes2.ts, 22, 28)) +} + +// Repros from #22860 + +class Opt { +>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, 29, 14)) +>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 29, 10)) + + return undefined; +>undefined : Symbol(undefined) + } +} + +interface Seq { +>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, 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, 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, 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, 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, 39, 13)) +>U : Symbol(U, Decl(conditionalTypes2.ts, 43, 15)) + + partition2(predicate:(x:T)=>boolean): [Vector,Vector]; +>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, 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) + } +} + +interface A1 { +>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, 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, 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, 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, 55, 19)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13)) +} + diff --git a/tests/baselines/reference/conditionalTypes2.types b/tests/baselines/reference/conditionalTypes2.types new file mode 100644 index 0000000000000..e3dad1fc280e5 --- /dev/null +++ b/tests/baselines/reference/conditionalTypes2.types @@ -0,0 +1,218 @@ +=== 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 +} + +function f1(a: Covariant, b: Covariant) { +>f1 : (a: Covariant, b: Covariant) => void +>A : A +>B : B +>A : A +>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 : A +>B : B +>A : A +>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 : A +>B : B +>A : A +>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 +} + 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 +} + 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) { } +} diff --git a/tests/cases/conformance/types/conditional/conditionalTypes2.ts b/tests/cases/conformance/types/conditional/conditionalTypes2.ts new file mode 100644 index 0000000000000..5ba189236b05b --- /dev/null +++ b/tests/cases/conformance/types/conditional/conditionalTypes2.ts @@ -0,0 +1,61 @@ +// @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; +} + +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 +} 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(); 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