From 8885d7941ca2a2d0face91a3e848653f03ba58ae Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 6 Feb 2018 13:24:53 -0800 Subject: [PATCH 1/8] Infer constraints for 'infer T' declarations nested in type references --- src/compiler/checker.ts | 126 ++++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 44 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a93189c81f2..83369c5cc3d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6963,6 +6963,29 @@ namespace ts { return type.symbol && getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter).constraint; } + function getInferredTypeParameterConstraint(typeParameter: TypeParameter) { + let constraints: Type[]; + if (typeParameter.symbol) { + for (const declaration of typeParameter.symbol.declarations) { + // When an 'infer T' declaration is immediately contained in a type reference node + // (such as 'Foo'), T's constraint is inferred from the constraint of the + // corresponding type parameter in 'Foo'. When multiple 'infer T' declarations are + // present, we form an intersection of the inferred constraint types. + if (declaration.parent.kind === SyntaxKind.InferType && declaration.parent.parent.kind === SyntaxKind.TypeReference) { + const typeReference = declaration.parent.parent; + const typeParameters = getTypeParametersForTypeReference(typeReference); + if (typeParameters) { + const index = typeReference.typeArguments.indexOf(declaration.parent); + if (index < typeParameters.length) { + constraints = append(constraints, getBaseConstraintOfType(typeParameters[index])); + } + } + } + } + } + return constraints && getIntersectionType(constraints); + } + function getConstraintFromTypeParameter(typeParameter: TypeParameter): Type { if (!typeParameter.constraint) { if (typeParameter.target) { @@ -6971,7 +6994,8 @@ namespace ts { } else { const constraintDeclaration = getConstraintDeclaration(typeParameter); - typeParameter.constraint = constraintDeclaration ? getTypeFromTypeNode(constraintDeclaration) : noConstraintType; + typeParameter.constraint = constraintDeclaration ? getTypeFromTypeNode(constraintDeclaration) : + getInferredTypeParameterConstraint(typeParameter) || noConstraintType; } } return typeParameter.constraint === noConstraintType ? undefined : typeParameter.constraint; @@ -7078,12 +7102,8 @@ namespace ts { const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgs, typeParameters, minTypeArgumentCount, isJs)); return createTypeReference(type, typeArguments); } - if (node.typeArguments) { - error(node, Diagnostics.Type_0_is_not_generic, typeToString(type)); - return unknownType; + return checkNoTypeArguments(node, symbol) ? type : unknownType; } - return type; - } function getTypeAliasInstantiation(symbol: Symbol, typeArguments: Type[]): Type { const type = getDeclaredTypeOfSymbol(symbol); @@ -7120,12 +7140,8 @@ namespace ts { } return getTypeAliasInstantiation(symbol, typeArguments); } - if (node.typeArguments) { - error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol)); - return unknownType; + return checkNoTypeArguments(node, symbol) ? type : unknownType; } - return type; - } function getTypeReferenceName(node: TypeReferenceType): EntityNameOrEntityNameExpression | undefined { switch (node.kind) { @@ -7165,12 +7181,10 @@ namespace ts { // Get type from reference to named type that cannot be generic (enum or type parameter) const res = tryGetDeclaredTypeOfSymbol(symbol); - if (res !== undefined) { - if (typeArguments) { - error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol)); - return unknownType; - } - return res.flags & TypeFlags.TypeParameter ? getConstrainedTypeParameter(res, node) : res; + if (res) { + return checkNoTypeArguments(node, symbol) ? + res.flags & TypeFlags.TypeParameter ? getConstrainedTypeParameter(res, node) : res : + unknownType; } if (!(symbol.flags & SymbolFlags.Value && isJSDocTypeReference(node))) { @@ -7234,39 +7248,58 @@ namespace ts { return node.flags & NodeFlags.JSDoc && node.kind === SyntaxKind.TypeReference; } + function checkNoTypeArguments(node: TypeReferenceType, symbol?: Symbol) { + if (node.typeArguments) { + error(node, Diagnostics.Type_0_is_not_generic, symbol ? symbolToString(symbol) : declarationNameToString((node).typeName)); + return false; + } + return true; + } + function getIntendedTypeFromJSDocTypeReference(node: TypeReferenceNode): Type { if (isIdentifier(node.typeName)) { - if (node.typeName.escapedText === "Object") { - if (isJSDocIndexSignature(node)) { - const indexed = getTypeFromTypeNode(node.typeArguments[0]); - const target = getTypeFromTypeNode(node.typeArguments[1]); - const index = createIndexInfo(target, /*isReadonly*/ false); - return createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, indexed === stringType && index, indexed === numberType && index); - } - return anyType; - } + const typeArgs = node.typeArguments; switch (node.typeName.escapedText) { case "String": + checkNoTypeArguments(node); return stringType; case "Number": + checkNoTypeArguments(node); return numberType; case "Boolean": + checkNoTypeArguments(node); return booleanType; case "Void": + checkNoTypeArguments(node); return voidType; case "Undefined": + checkNoTypeArguments(node); return undefinedType; case "Null": + checkNoTypeArguments(node); return nullType; case "Function": case "function": + checkNoTypeArguments(node); return globalFunctionType; case "Array": case "array": - return !node.typeArguments || !node.typeArguments.length ? anyArrayType : undefined; + return !typeArgs || !typeArgs.length ? anyArrayType : undefined; case "Promise": case "promise": - return !node.typeArguments || !node.typeArguments.length ? createPromiseType(anyType) : undefined; + return !typeArgs || !typeArgs.length ? createPromiseType(anyType) : undefined; + case "Object": + if (typeArgs && typeArgs.length === 2) { + if (isJSDocIndexSignature(node)) { + const indexed = getTypeFromTypeNode(typeArgs[0]); + const target = getTypeFromTypeNode(typeArgs[1]); + const index = createIndexInfo(target, /*isReadonly*/ false); + return createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, indexed === stringType && index, indexed === numberType && index); + } + return anyType; + } + checkNoTypeArguments(node); + return anyType; } } } @@ -8781,7 +8814,7 @@ namespace ts { } function isMappableType(type: Type) { - return type.flags & (TypeFlags.Any | TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.Intersection | TypeFlags.IndexedAccess); + return type.flags & (TypeFlags.Any | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection); } function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): AnonymousType { @@ -20182,6 +20215,23 @@ namespace ts { return result; } + function getTypeParametersForTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments) { + const type = getTypeFromTypeReference(node); + if (type !== unknownType) { + const symbol = getNodeLinks(node).resolvedSymbol; + if (symbol) { + const typeAliasParameters = symbol.flags & SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters; + if (typeAliasParameters) { + return typeAliasParameters; + } + if (getObjectFlags(type) & ObjectFlags.Reference) { + return (type).target.localTypeParameters; + } + } + } + return undefined; + } + function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) { checkGrammarTypeArguments(node, node.typeArguments); if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJavaScriptFile(node) && !isInJSDoc(node)) { @@ -20194,22 +20244,10 @@ namespace ts { // Do type argument local checks only if referenced type is successfully resolved forEach(node.typeArguments, checkSourceElement); if (produceDiagnostics) { - const symbol = getNodeLinks(node).resolvedSymbol; - if (!symbol) { - // There is no resolved symbol cached if the type resolved to a builtin - // via JSDoc type reference resolution (eg, Boolean became boolean), none - // of which are generic when they have no associated symbol - // (additionally, JSDoc's index signature syntax, Object actually uses generic syntax without being generic) - if (!isJSDocIndexSignature(node)) { - error(node, Diagnostics.Type_0_is_not_generic, typeToString(type)); - } - return; + const typeParameters = getTypeParametersForTypeReference(node); + if (typeParameters) { + checkTypeArgumentConstraints(typeParameters, node.typeArguments); } - let typeParameters = symbol.flags & SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters; - if (!typeParameters && getObjectFlags(type) & ObjectFlags.Reference) { - typeParameters = (type).target.localTypeParameters; - } - checkTypeArgumentConstraints(typeParameters, node.typeArguments); } } if (type.flags & TypeFlags.Enum && getNodeLinks(node).resolvedSymbol.flags & SymbolFlags.EnumMember) { From af8150363b6faf94d00438462d1af02a8c855289 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 6 Feb 2018 13:25:18 -0800 Subject: [PATCH 2/8] Accept baseline changes from code refactoring --- ...eNongenericInstantiationAttempt.errors.txt | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/baselines/reference/jsdocTypeNongenericInstantiationAttempt.errors.txt b/tests/baselines/reference/jsdocTypeNongenericInstantiationAttempt.errors.txt index 645eca539f4..941e4386f99 100644 --- a/tests/baselines/reference/jsdocTypeNongenericInstantiationAttempt.errors.txt +++ b/tests/baselines/reference/jsdocTypeNongenericInstantiationAttempt.errors.txt @@ -1,10 +1,10 @@ -tests/cases/compiler/index.js(2,19): error TS2315: Type 'boolean' is not generic. -tests/cases/compiler/index2.js(2,19): error TS2315: Type 'void' is not generic. -tests/cases/compiler/index3.js(2,19): error TS2315: Type 'undefined' is not generic. +tests/cases/compiler/index.js(2,19): error TS2315: Type 'Boolean' is not generic. +tests/cases/compiler/index2.js(2,19): error TS2315: Type 'Void' is not generic. +tests/cases/compiler/index3.js(2,19): error TS2315: Type 'Undefined' is not generic. tests/cases/compiler/index4.js(2,19): error TS2315: Type 'Function' is not generic. -tests/cases/compiler/index5.js(2,19): error TS2315: Type 'string' is not generic. -tests/cases/compiler/index6.js(2,19): error TS2315: Type 'number' is not generic. -tests/cases/compiler/index7.js(2,19): error TS2315: Type 'any' is not generic. +tests/cases/compiler/index5.js(2,19): error TS2315: Type 'String' is not generic. +tests/cases/compiler/index6.js(2,19): error TS2315: Type 'Number' is not generic. +tests/cases/compiler/index7.js(2,19): error TS2315: Type 'Object' is not generic. tests/cases/compiler/index8.js(4,12): error TS2304: Cannot find name 'fn'. tests/cases/compiler/index8.js(4,15): error TS2304: Cannot find name 'T'. @@ -13,7 +13,7 @@ tests/cases/compiler/index8.js(4,15): error TS2304: Cannot find name 'T'. /** * @param {(m: Boolean) => string} somebody ~~~~~~~~~~ -!!! error TS2315: Type 'boolean' is not generic. +!!! error TS2315: Type 'Boolean' is not generic. */ function sayHello(somebody) { return 'Hello ' + somebody; @@ -23,7 +23,7 @@ tests/cases/compiler/index8.js(4,15): error TS2304: Cannot find name 'T'. /** * @param {(m: Void) => string} somebody ~~~~~~~ -!!! error TS2315: Type 'void' is not generic. +!!! error TS2315: Type 'Void' is not generic. */ function sayHello2(somebody) { return 'Hello ' + somebody; @@ -34,7 +34,7 @@ tests/cases/compiler/index8.js(4,15): error TS2304: Cannot find name 'T'. /** * @param {(m: Undefined) => string} somebody ~~~~~~~~~~~~ -!!! error TS2315: Type 'undefined' is not generic. +!!! error TS2315: Type 'Undefined' is not generic. */ function sayHello3(somebody) { return 'Hello ' + somebody; @@ -56,7 +56,7 @@ tests/cases/compiler/index8.js(4,15): error TS2304: Cannot find name 'T'. /** * @param {(m: String) => string} somebody ~~~~~~~~~ -!!! error TS2315: Type 'string' is not generic. +!!! error TS2315: Type 'String' is not generic. */ function sayHello5(somebody) { return 'Hello ' + somebody; @@ -67,7 +67,7 @@ tests/cases/compiler/index8.js(4,15): error TS2304: Cannot find name 'T'. /** * @param {(m: Number) => string} somebody ~~~~~~~~~ -!!! error TS2315: Type 'number' is not generic. +!!! error TS2315: Type 'Number' is not generic. */ function sayHello6(somebody) { return 'Hello ' + somebody; @@ -78,7 +78,7 @@ tests/cases/compiler/index8.js(4,15): error TS2304: Cannot find name 'T'. /** * @param {(m: Object) => string} somebody ~~~~~~~~~ -!!! error TS2315: Type 'any' is not generic. +!!! error TS2315: Type 'Object' is not generic. */ function sayHello7(somebody) { return 'Hello ' + somebody; From e62abbb9f8141126e45eaee4c748448ba35253c3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 6 Feb 2018 17:21:18 -0800 Subject: [PATCH 3/8] Instantiate inferred type parameter constraints --- src/compiler/checker.ts | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 83369c5cc3d..52cd6a37024 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6977,7 +6977,11 @@ namespace ts { if (typeParameters) { const index = typeReference.typeArguments.indexOf(declaration.parent); if (index < typeParameters.length) { - constraints = append(constraints, getBaseConstraintOfType(typeParameters[index])); + const constraint = getConstraintOfTypeParameter(typeParameters[index]); + if (constraint) { + const mapper = createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReference, typeParameters)); + constraints = append(constraints, instantiateType(constraint, mapper)); + } } } } @@ -20192,8 +20196,12 @@ namespace ts { checkDecorators(node); } - function checkTypeArgumentConstraints(typeParameters: TypeParameter[], typeArgumentNodes: ReadonlyArray): boolean { + function getEffectiveTypeArguments(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: TypeParameter[]) { const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); + return fillMissingTypeArguments(map(node.typeArguments, getTypeFromTypeNode), typeParameters, minTypeArgumentCount, isInJavaScriptFile(node)); + } + + function checkTypeArgumentConstraints(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: TypeParameter[]): boolean { let typeArguments: Type[]; let mapper: TypeMapper; let result = true; @@ -20201,14 +20209,14 @@ namespace ts { const constraint = getConstraintOfTypeParameter(typeParameters[i]); if (constraint) { if (!typeArguments) { - typeArguments = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, minTypeArgumentCount, isInJavaScriptFile(typeArgumentNodes[i])); + typeArguments = getEffectiveTypeArguments(node, typeParameters); mapper = createTypeMapper(typeParameters, typeArguments); } const typeArgument = typeArguments[i]; result = result && checkTypeAssignableTo( typeArgument, instantiateType(constraint, mapper), - typeArgumentNodes[i], + node.typeArguments[i], Diagnostics.Type_0_does_not_satisfy_the_constraint_1); } } @@ -20220,13 +20228,8 @@ namespace ts { if (type !== unknownType) { const symbol = getNodeLinks(node).resolvedSymbol; if (symbol) { - const typeAliasParameters = symbol.flags & SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters; - if (typeAliasParameters) { - return typeAliasParameters; - } - if (getObjectFlags(type) & ObjectFlags.Reference) { - return (type).target.localTypeParameters; - } + return symbol.flags & SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters || + (getObjectFlags(type) & ObjectFlags.Reference ? (type).target.localTypeParameters : undefined); } } return undefined; @@ -20236,7 +20239,6 @@ namespace ts { checkGrammarTypeArguments(node, node.typeArguments); if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJavaScriptFile(node) && !isInJSDoc(node)) { grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); - } const type = getTypeFromTypeReference(node); if (type !== unknownType) { @@ -20246,7 +20248,7 @@ namespace ts { if (produceDiagnostics) { const typeParameters = getTypeParametersForTypeReference(node); if (typeParameters) { - checkTypeArgumentConstraints(typeParameters, node.typeArguments); + checkTypeArgumentConstraints(node, typeParameters); } } } @@ -22944,7 +22946,7 @@ namespace ts { if (some(baseTypeNode.typeArguments)) { forEach(baseTypeNode.typeArguments, checkSourceElement); for (const constructor of getConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode)) { - if (!checkTypeArgumentConstraints(constructor.typeParameters, baseTypeNode.typeArguments)) { + if (!checkTypeArgumentConstraints(baseTypeNode, constructor.typeParameters)) { break; } } From 1f3af4eab205754aa33ae764b80223eddb62cbb4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 6 Feb 2018 17:33:02 -0800 Subject: [PATCH 4/8] Add tests --- .../types/conditional/inferTypes1.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/cases/conformance/types/conditional/inferTypes1.ts b/tests/cases/conformance/types/conditional/inferTypes1.ts index 6ff7ae67c89..370e5b358b6 100644 --- a/tests/cases/conformance/types/conditional/inferTypes1.ts +++ b/tests/cases/conformance/types/conditional/inferTypes1.ts @@ -74,6 +74,18 @@ type T60 = infer U; // Error type T61 = infer A extends infer B ? infer C : infer D; // Error type T62 = U extends (infer U)[] ? U : U; // Error +type T70 = { x: T }; +type T71 = T extends T70 ? T70 : never; + +type T72 = { y: T }; +type T73 = T extends T72 ? T70 : never; // Error + +type T74 = { x: T, y: U }; +type T75 = T extends T74 ? T70 | T72 | T74 : never; + +type T76 = { x: T }; +type T77 = T extends T76 ? T76: never; + // Example from #21496 type JsonifiedObject = { [K in keyof T]: Jsonified }; @@ -105,3 +117,12 @@ type JsonifiedExample = Jsonified; declare let ex: JsonifiedExample; const z1: "correct" = ex.customClass; const z2: string = ex.obj.nested.attr; + +// Repros from #21631 + +type A1> = [T, U]; +type B1 = S extends A1 ? [T, U] : never; + +type A2 = [T, U]; +type B2 = S extends A2 ? [T, U] : never; +type C2 = S extends A2 ? [T, U] : never; From 39db00e58884e2bab5aef2dd85d239c916465261 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 6 Feb 2018 17:33:09 -0800 Subject: [PATCH 5/8] Accept new baselines --- .../reference/inferTypes1.errors.txt | 28 ++- tests/baselines/reference/inferTypes1.js | 21 ++ tests/baselines/reference/inferTypes1.symbols | 222 ++++++++++++++---- tests/baselines/reference/inferTypes1.types | 122 ++++++++++ 4 files changed, 342 insertions(+), 51 deletions(-) diff --git a/tests/baselines/reference/inferTypes1.errors.txt b/tests/baselines/reference/inferTypes1.errors.txt index ff93491dd1d..d8dea7d9868 100644 --- a/tests/baselines/reference/inferTypes1.errors.txt +++ b/tests/baselines/reference/inferTypes1.errors.txt @@ -10,9 +10,11 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(72,15): error TS2304: C tests/cases/conformance/types/conditional/inferTypes1.ts(72,15): error TS4081: Exported type alias 'T62' has or is using private name 'U'. tests/cases/conformance/types/conditional/inferTypes1.ts(72,43): error TS2304: Cannot find name 'U'. tests/cases/conformance/types/conditional/inferTypes1.ts(72,43): error TS4081: Exported type alias 'T62' has or is using private name 'U'. +tests/cases/conformance/types/conditional/inferTypes1.ts(78,44): error TS2344: Type 'U' does not satisfy the constraint 'string'. + Type 'number' is not assignable to type 'string'. -==== tests/cases/conformance/types/conditional/inferTypes1.ts (11 errors) ==== +==== tests/cases/conformance/types/conditional/inferTypes1.ts (12 errors) ==== type Unpacked = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : @@ -109,6 +111,21 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(72,43): error TS4081: E ~ !!! error TS4081: Exported type alias 'T62' has or is using private name 'U'. + type T70 = { x: T }; + type T71 = T extends T70 ? T70 : never; + + type T72 = { y: T }; + type T73 = T extends T72 ? T70 : never; // Error + ~ +!!! error TS2344: Type 'U' does not satisfy the constraint 'string'. +!!! error TS2344: Type 'number' is not assignable to type 'string'. + + type T74 = { x: T, y: U }; + type T75 = T extends T74 ? T70 | T72 | T74 : never; + + type T76 = { x: T }; + type T77 = T extends T76 ? T76: never; + // Example from #21496 type JsonifiedObject = { [K in keyof T]: Jsonified }; @@ -140,4 +157,13 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(72,43): error TS4081: E declare let ex: JsonifiedExample; const z1: "correct" = ex.customClass; const z2: string = ex.obj.nested.attr; + + // Repros from #21631 + + type A1> = [T, U]; + type B1 = S extends A1 ? [T, U] : never; + + type A2 = [T, U]; + type B2 = S extends A2 ? [T, U] : never; + type C2 = S extends A2 ? [T, U] : never; \ No newline at end of file diff --git a/tests/baselines/reference/inferTypes1.js b/tests/baselines/reference/inferTypes1.js index 5a692fe8d05..f916464f2fe 100644 --- a/tests/baselines/reference/inferTypes1.js +++ b/tests/baselines/reference/inferTypes1.js @@ -72,6 +72,18 @@ type T60 = infer U; // Error type T61 = infer A extends infer B ? infer C : infer D; // Error type T62 = U extends (infer U)[] ? U : U; // Error +type T70 = { x: T }; +type T71 = T extends T70 ? T70 : never; + +type T72 = { y: T }; +type T73 = T extends T72 ? T70 : never; // Error + +type T74 = { x: T, y: U }; +type T75 = T extends T74 ? T70 | T72 | T74 : never; + +type T76 = { x: T }; +type T77 = T extends T76 ? T76: never; + // Example from #21496 type JsonifiedObject = { [K in keyof T]: Jsonified }; @@ -103,6 +115,15 @@ type JsonifiedExample = Jsonified; declare let ex: JsonifiedExample; const z1: "correct" = ex.customClass; const z2: string = ex.obj.nested.attr; + +// Repros from #21631 + +type A1> = [T, U]; +type B1 = S extends A1 ? [T, U] : never; + +type A2 = [T, U]; +type B2 = S extends A2 ? [T, U] : never; +type C2 = S extends A2 ? [T, U] : never; //// [inferTypes1.js] diff --git a/tests/baselines/reference/inferTypes1.symbols b/tests/baselines/reference/inferTypes1.symbols index 18674d957a8..e3772e89f01 100644 --- a/tests/baselines/reference/inferTypes1.symbols +++ b/tests/baselines/reference/inferTypes1.symbols @@ -315,106 +315,228 @@ type T62 = U extends (infer U)[] ? U : U; // Error >U : Symbol(U, Decl(inferTypes1.ts, 71, 30)) >U : Symbol(U, Decl(inferTypes1.ts, 71, 30)) +type T70 = { x: T }; +>T70 : Symbol(T70, Decl(inferTypes1.ts, 71, 44)) +>T : Symbol(T, Decl(inferTypes1.ts, 73, 9)) +>x : Symbol(x, Decl(inferTypes1.ts, 73, 30)) +>T : Symbol(T, Decl(inferTypes1.ts, 73, 9)) + +type T71 = T extends T70 ? T70 : never; +>T71 : Symbol(T71, Decl(inferTypes1.ts, 73, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 74, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 74, 9)) +>T70 : Symbol(T70, Decl(inferTypes1.ts, 71, 44)) +>U : Symbol(U, Decl(inferTypes1.ts, 74, 33)) +>T70 : Symbol(T70, Decl(inferTypes1.ts, 71, 44)) +>U : Symbol(U, Decl(inferTypes1.ts, 74, 33)) + +type T72 = { y: T }; +>T72 : Symbol(T72, Decl(inferTypes1.ts, 74, 54)) +>T : Symbol(T, Decl(inferTypes1.ts, 76, 9)) +>y : Symbol(y, Decl(inferTypes1.ts, 76, 30)) +>T : Symbol(T, Decl(inferTypes1.ts, 76, 9)) + +type T73 = T extends T72 ? T70 : never; // Error +>T73 : Symbol(T73, Decl(inferTypes1.ts, 76, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 77, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 77, 9)) +>T72 : Symbol(T72, Decl(inferTypes1.ts, 74, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 77, 33)) +>T70 : Symbol(T70, Decl(inferTypes1.ts, 71, 44)) +>U : Symbol(U, Decl(inferTypes1.ts, 77, 33)) + +type T74 = { x: T, y: U }; +>T74 : Symbol(T74, Decl(inferTypes1.ts, 77, 54)) +>T : Symbol(T, Decl(inferTypes1.ts, 79, 9)) +>U : Symbol(U, Decl(inferTypes1.ts, 79, 26)) +>x : Symbol(x, Decl(inferTypes1.ts, 79, 48)) +>T : Symbol(T, Decl(inferTypes1.ts, 79, 9)) +>y : Symbol(y, Decl(inferTypes1.ts, 79, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 79, 26)) + +type T75 = T extends T74 ? T70 | T72 | T74 : never; +>T75 : Symbol(T75, Decl(inferTypes1.ts, 79, 62)) +>T : Symbol(T, Decl(inferTypes1.ts, 80, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 80, 9)) +>T74 : Symbol(T74, Decl(inferTypes1.ts, 77, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) +>U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) +>T70 : Symbol(T70, Decl(inferTypes1.ts, 71, 44)) +>U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) +>T72 : Symbol(T72, Decl(inferTypes1.ts, 74, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) +>T74 : Symbol(T74, Decl(inferTypes1.ts, 77, 54)) +>U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) +>U : Symbol(U, Decl(inferTypes1.ts, 80, 33), Decl(inferTypes1.ts, 80, 42)) + +type T76 = { x: T }; +>T76 : Symbol(T76, Decl(inferTypes1.ts, 80, 84)) +>T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) +>U : Symbol(U, Decl(inferTypes1.ts, 82, 23)) +>T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) +>x : Symbol(x, Decl(inferTypes1.ts, 82, 40)) +>T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) + +type T77 = T extends T76 ? T76: never; +>T77 : Symbol(T77, Decl(inferTypes1.ts, 82, 48)) +>T : Symbol(T, Decl(inferTypes1.ts, 83, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 83, 9)) +>T76 : Symbol(T76, Decl(inferTypes1.ts, 80, 84)) +>X : Symbol(X, Decl(inferTypes1.ts, 83, 33)) +>Y : Symbol(Y, Decl(inferTypes1.ts, 83, 42)) +>T76 : Symbol(T76, Decl(inferTypes1.ts, 80, 84)) +>X : Symbol(X, Decl(inferTypes1.ts, 83, 33)) +>Y : Symbol(Y, Decl(inferTypes1.ts, 83, 42)) + // Example from #21496 type JsonifiedObject = { [K in keyof T]: Jsonified }; ->JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 71, 44)) ->T : Symbol(T, Decl(inferTypes1.ts, 75, 21)) ->K : Symbol(K, Decl(inferTypes1.ts, 75, 44)) ->T : Symbol(T, Decl(inferTypes1.ts, 75, 21)) ->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 75, 77)) ->T : Symbol(T, Decl(inferTypes1.ts, 75, 21)) ->K : Symbol(K, Decl(inferTypes1.ts, 75, 44)) +>JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 83, 65)) +>T : Symbol(T, Decl(inferTypes1.ts, 87, 21)) +>K : Symbol(K, Decl(inferTypes1.ts, 87, 44)) +>T : Symbol(T, Decl(inferTypes1.ts, 87, 21)) +>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 87, 77)) +>T : Symbol(T, Decl(inferTypes1.ts, 87, 21)) +>K : Symbol(K, Decl(inferTypes1.ts, 87, 44)) type Jsonified = ->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 75, 77)) ->T : Symbol(T, Decl(inferTypes1.ts, 77, 15)) +>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 87, 77)) +>T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) T extends string | number | boolean | null ? T ->T : Symbol(T, Decl(inferTypes1.ts, 77, 15)) ->T : Symbol(T, Decl(inferTypes1.ts, 77, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) : T extends undefined | Function ? never // undefined and functions are removed ->T : Symbol(T, Decl(inferTypes1.ts, 77, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) : T extends { toJSON(): infer R } ? R // toJSON is called if it exists (e.g. Date) ->T : Symbol(T, Decl(inferTypes1.ts, 77, 15)) ->toJSON : Symbol(toJSON, Decl(inferTypes1.ts, 80, 17)) ->R : Symbol(R, Decl(inferTypes1.ts, 80, 33)) ->R : Symbol(R, Decl(inferTypes1.ts, 80, 33)) +>T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) +>toJSON : Symbol(toJSON, Decl(inferTypes1.ts, 92, 17)) +>R : Symbol(R, Decl(inferTypes1.ts, 92, 33)) +>R : Symbol(R, Decl(inferTypes1.ts, 92, 33)) : T extends object ? JsonifiedObject ->T : Symbol(T, Decl(inferTypes1.ts, 77, 15)) ->JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 71, 44)) ->T : Symbol(T, Decl(inferTypes1.ts, 77, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) +>JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 83, 65)) +>T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) : "what is this"; type Example = { ->Example : Symbol(Example, Decl(inferTypes1.ts, 82, 21)) +>Example : Symbol(Example, Decl(inferTypes1.ts, 94, 21)) str: "literalstring", ->str : Symbol(str, Decl(inferTypes1.ts, 84, 16)) +>str : Symbol(str, Decl(inferTypes1.ts, 96, 16)) fn: () => void, ->fn : Symbol(fn, Decl(inferTypes1.ts, 85, 25)) +>fn : Symbol(fn, Decl(inferTypes1.ts, 97, 25)) date: Date, ->date : Symbol(date, Decl(inferTypes1.ts, 86, 19)) +>date : Symbol(date, Decl(inferTypes1.ts, 98, 19)) >Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) customClass: MyClass, ->customClass : Symbol(customClass, Decl(inferTypes1.ts, 87, 15)) ->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 94, 1)) +>customClass : Symbol(customClass, Decl(inferTypes1.ts, 99, 15)) +>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 106, 1)) obj: { ->obj : Symbol(obj, Decl(inferTypes1.ts, 88, 25)) +>obj : Symbol(obj, Decl(inferTypes1.ts, 100, 25)) prop: "property", ->prop : Symbol(prop, Decl(inferTypes1.ts, 89, 10)) +>prop : Symbol(prop, Decl(inferTypes1.ts, 101, 10)) clz: MyClass, ->clz : Symbol(clz, Decl(inferTypes1.ts, 90, 25)) ->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 94, 1)) +>clz : Symbol(clz, Decl(inferTypes1.ts, 102, 25)) +>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 106, 1)) nested: { attr: Date } ->nested : Symbol(nested, Decl(inferTypes1.ts, 91, 21)) ->attr : Symbol(attr, Decl(inferTypes1.ts, 92, 17)) +>nested : Symbol(nested, Decl(inferTypes1.ts, 103, 21)) +>attr : Symbol(attr, Decl(inferTypes1.ts, 104, 17)) >Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) }, } declare class MyClass { ->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 94, 1)) +>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 106, 1)) toJSON(): "correct"; ->toJSON : Symbol(MyClass.toJSON, Decl(inferTypes1.ts, 96, 23)) +>toJSON : Symbol(MyClass.toJSON, Decl(inferTypes1.ts, 108, 23)) } type JsonifiedExample = Jsonified; ->JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 98, 1)) ->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 75, 77)) ->Example : Symbol(Example, Decl(inferTypes1.ts, 82, 21)) +>JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 110, 1)) +>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 87, 77)) +>Example : Symbol(Example, Decl(inferTypes1.ts, 94, 21)) declare let ex: JsonifiedExample; ->ex : Symbol(ex, Decl(inferTypes1.ts, 101, 11)) ->JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 98, 1)) +>ex : Symbol(ex, Decl(inferTypes1.ts, 113, 11)) +>JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 110, 1)) const z1: "correct" = ex.customClass; ->z1 : Symbol(z1, Decl(inferTypes1.ts, 102, 5)) ->ex.customClass : Symbol(customClass, Decl(inferTypes1.ts, 87, 15)) ->ex : Symbol(ex, Decl(inferTypes1.ts, 101, 11)) ->customClass : Symbol(customClass, Decl(inferTypes1.ts, 87, 15)) +>z1 : Symbol(z1, Decl(inferTypes1.ts, 114, 5)) +>ex.customClass : Symbol(customClass, Decl(inferTypes1.ts, 99, 15)) +>ex : Symbol(ex, Decl(inferTypes1.ts, 113, 11)) +>customClass : Symbol(customClass, Decl(inferTypes1.ts, 99, 15)) const z2: string = ex.obj.nested.attr; ->z2 : Symbol(z2, Decl(inferTypes1.ts, 103, 5)) ->ex.obj.nested.attr : Symbol(attr, Decl(inferTypes1.ts, 92, 17)) ->ex.obj.nested : Symbol(nested, Decl(inferTypes1.ts, 91, 21)) ->ex.obj : Symbol(obj, Decl(inferTypes1.ts, 88, 25)) ->ex : Symbol(ex, Decl(inferTypes1.ts, 101, 11)) ->obj : Symbol(obj, Decl(inferTypes1.ts, 88, 25)) ->nested : Symbol(nested, Decl(inferTypes1.ts, 91, 21)) ->attr : Symbol(attr, Decl(inferTypes1.ts, 92, 17)) +>z2 : Symbol(z2, Decl(inferTypes1.ts, 115, 5)) +>ex.obj.nested.attr : Symbol(attr, Decl(inferTypes1.ts, 104, 17)) +>ex.obj.nested : Symbol(nested, Decl(inferTypes1.ts, 103, 21)) +>ex.obj : Symbol(obj, Decl(inferTypes1.ts, 100, 25)) +>ex : Symbol(ex, Decl(inferTypes1.ts, 113, 11)) +>obj : Symbol(obj, Decl(inferTypes1.ts, 100, 25)) +>nested : Symbol(nested, Decl(inferTypes1.ts, 103, 21)) +>attr : Symbol(attr, Decl(inferTypes1.ts, 104, 17)) + +// Repros from #21631 + +type A1> = [T, U]; +>A1 : Symbol(A1, Decl(inferTypes1.ts, 115, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 119, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 119, 10)) +>A1 : Symbol(A1, Decl(inferTypes1.ts, 115, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 119, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 119, 10)) + +type B1 = S extends A1 ? [T, U] : never; +>B1 : Symbol(B1, Decl(inferTypes1.ts, 119, 44)) +>S : Symbol(S, Decl(inferTypes1.ts, 120, 8)) +>S : Symbol(S, Decl(inferTypes1.ts, 120, 8)) +>A1 : Symbol(A1, Decl(inferTypes1.ts, 115, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 120, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 120, 40)) +>T : Symbol(T, Decl(inferTypes1.ts, 120, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 120, 40)) + +type A2 = [T, U]; +>A2 : Symbol(A2, Decl(inferTypes1.ts, 120, 61)) +>T : Symbol(T, Decl(inferTypes1.ts, 122, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 122, 10)) +>T : Symbol(T, Decl(inferTypes1.ts, 122, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 122, 10)) + +type B2 = S extends A2 ? [T, U] : never; +>B2 : Symbol(B2, Decl(inferTypes1.ts, 122, 36)) +>S : Symbol(S, Decl(inferTypes1.ts, 123, 8)) +>S : Symbol(S, Decl(inferTypes1.ts, 123, 8)) +>A2 : Symbol(A2, Decl(inferTypes1.ts, 120, 61)) +>T : Symbol(T, Decl(inferTypes1.ts, 123, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 123, 40)) +>T : Symbol(T, Decl(inferTypes1.ts, 123, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 123, 40)) + +type C2 = S extends A2 ? [T, U] : never; +>C2 : Symbol(C2, Decl(inferTypes1.ts, 123, 61)) +>S : Symbol(S, Decl(inferTypes1.ts, 124, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 124, 10)) +>S : Symbol(S, Decl(inferTypes1.ts, 124, 8)) +>A2 : Symbol(A2, Decl(inferTypes1.ts, 120, 61)) +>T : Symbol(T, Decl(inferTypes1.ts, 124, 47)) +>U : Symbol(U, Decl(inferTypes1.ts, 124, 10)) +>T : Symbol(T, Decl(inferTypes1.ts, 124, 47)) +>U : Symbol(U, Decl(inferTypes1.ts, 124, 10)) diff --git a/tests/baselines/reference/inferTypes1.types b/tests/baselines/reference/inferTypes1.types index 0b753c30f49..4f050958773 100644 --- a/tests/baselines/reference/inferTypes1.types +++ b/tests/baselines/reference/inferTypes1.types @@ -321,6 +321,80 @@ type T62 = U extends (infer U)[] ? U : U; // Error >U : U >U : No type information available! +type T70 = { x: T }; +>T70 : T70 +>T : T +>x : T +>T : T + +type T71 = T extends T70 ? T70 : never; +>T71 : T71 +>T : T +>T : T +>T70 : T70 +>U : U +>T70 : T70 +>U : U + +type T72 = { y: T }; +>T72 : T72 +>T : T +>y : T +>T : T + +type T73 = T extends T72 ? T70 : never; // Error +>T73 : T73 +>T : T +>T : T +>T72 : T72 +>U : U +>T70 : T70 +>U : U + +type T74 = { x: T, y: U }; +>T74 : T74 +>T : T +>U : U +>x : T +>T : T +>y : U +>U : U + +type T75 = T extends T74 ? T70 | T72 | T74 : never; +>T75 : T75 +>T : T +>T : T +>T74 : T74 +>U : U +>U : U +>T70 : T70 +>U : U +>T72 : T72 +>U : U +>T74 : T74 +>U : U +>U : U + +type T76 = { x: T }; +>T76 : T76 +>T : T +>T : T +>U : U +>T : T +>x : T +>T : T + +type T77 = T extends T76 ? T76: never; +>T77 : T77 +>T : T +>T : T +>T76 : T76 +>X : X +>Y : Y +>T76 : T76 +>X : X +>Y : Y + // Example from #21496 type JsonifiedObject = { [K in keyof T]: Jsonified }; @@ -425,3 +499,51 @@ const z2: string = ex.obj.nested.attr; >nested : JsonifiedObject<{ attr: Date; }> >attr : string +// Repros from #21631 + +type A1> = [T, U]; +>A1 : [T, U] +>T : T +>U : U +>A1 : [T, U] +>T : T +>U : U + +type B1 = S extends A1 ? [T, U] : never; +>B1 : B1 +>S : S +>S : S +>A1 : [T, U] +>T : T +>U : U +>T : T +>U : U + +type A2 = [T, U]; +>A2 : [T, U] +>T : T +>U : U +>T : T +>U : U + +type B2 = S extends A2 ? [T, U] : never; +>B2 : B2 +>S : S +>S : S +>A2 : [T, U] +>T : T +>U : U +>T : T +>U : U + +type C2 = S extends A2 ? [T, U] : never; +>C2 : C2 +>S : S +>U : U +>S : S +>A2 : [T, U] +>T : T +>U : U +>T : T +>U : U + From a44ab9646810a8fc5a15a8edd96fbdb1877c95d1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 7 Feb 2018 06:57:23 -0800 Subject: [PATCH 6/8] Discard constraint inferences of the type parameter itself --- src/compiler/checker.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 52cd6a37024..60c1d1281ce 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6964,7 +6964,7 @@ namespace ts { } function getInferredTypeParameterConstraint(typeParameter: TypeParameter) { - let constraints: Type[]; + let inferences: Type[]; if (typeParameter.symbol) { for (const declaration of typeParameter.symbol.declarations) { // When an 'infer T' declaration is immediately contained in a type reference node @@ -6977,17 +6977,26 @@ namespace ts { if (typeParameters) { const index = typeReference.typeArguments.indexOf(declaration.parent); if (index < typeParameters.length) { - const constraint = getConstraintOfTypeParameter(typeParameters[index]); - if (constraint) { + const declaredConstraint = getConstraintOfTypeParameter(typeParameters[index]); + if (declaredConstraint) { + // Type parameter constraints can reference other type parameters so + // constraints need to be instantiated. If instantiation produces the + // type parameter itself, we discard that inference. For example, in + // type Foo = [T, U]; + // type Bar = T extends Foo ? Foo : T; + // the instantiated constraint for U is X, so we discard that inference. const mapper = createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReference, typeParameters)); - constraints = append(constraints, instantiateType(constraint, mapper)); + const constraint = instantiateType(declaredConstraint, mapper); + if (constraint !== typeParameter) { + inferences = append(inferences, constraint); + } } } } } } } - return constraints && getIntersectionType(constraints); + return inferences && getIntersectionType(inferences); } function getConstraintFromTypeParameter(typeParameter: TypeParameter): Type { @@ -20197,8 +20206,8 @@ namespace ts { } function getEffectiveTypeArguments(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: TypeParameter[]) { - const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); - return fillMissingTypeArguments(map(node.typeArguments, getTypeFromTypeNode), typeParameters, minTypeArgumentCount, isInJavaScriptFile(node)); + return fillMissingTypeArguments(map(node.typeArguments, getTypeFromTypeNode), typeParameters, + getMinTypeArgumentCount(typeParameters), isInJavaScriptFile(node)); } function checkTypeArgumentConstraints(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: TypeParameter[]): boolean { From 2dcd83c95427e1ab95839ce82a4eeface9fbf5af Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 7 Feb 2018 06:57:43 -0800 Subject: [PATCH 7/8] Add test --- tests/cases/conformance/types/conditional/inferTypes1.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/cases/conformance/types/conditional/inferTypes1.ts b/tests/cases/conformance/types/conditional/inferTypes1.ts index 370e5b358b6..08c7be5288e 100644 --- a/tests/cases/conformance/types/conditional/inferTypes1.ts +++ b/tests/cases/conformance/types/conditional/inferTypes1.ts @@ -84,7 +84,8 @@ type T74 = { x: T, y: U }; type T75 = T extends T74 ? T70 | T72 | T74 : never; type T76 = { x: T }; -type T77 = T extends T76 ? T76: never; +type T77 = T extends T76 ? T76 : never; +type T78 = T extends T76 ? T76 : never; // Example from #21496 From 61086e9e3834f2a524803cb3cd10db2cbf12ffc2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 7 Feb 2018 06:57:51 -0800 Subject: [PATCH 8/8] Accept new baselines --- .../reference/inferTypes1.errors.txt | 3 +- tests/baselines/reference/inferTypes1.js | 3 +- tests/baselines/reference/inferTypes1.symbols | 185 ++++++++++-------- tests/baselines/reference/inferTypes1.types | 13 +- 4 files changed, 114 insertions(+), 90 deletions(-) diff --git a/tests/baselines/reference/inferTypes1.errors.txt b/tests/baselines/reference/inferTypes1.errors.txt index d8dea7d9868..d5b91a426e3 100644 --- a/tests/baselines/reference/inferTypes1.errors.txt +++ b/tests/baselines/reference/inferTypes1.errors.txt @@ -124,7 +124,8 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(78,44): error TS2344: T type T75 = T extends T74 ? T70 | T72 | T74 : never; type T76 = { x: T }; - type T77 = T extends T76 ? T76: never; + type T77 = T extends T76 ? T76 : never; + type T78 = T extends T76 ? T76 : never; // Example from #21496 diff --git a/tests/baselines/reference/inferTypes1.js b/tests/baselines/reference/inferTypes1.js index f916464f2fe..56bc71e5a71 100644 --- a/tests/baselines/reference/inferTypes1.js +++ b/tests/baselines/reference/inferTypes1.js @@ -82,7 +82,8 @@ type T74 = { x: T, y: U }; type T75 = T extends T74 ? T70 | T72 | T74 : never; type T76 = { x: T }; -type T77 = T extends T76 ? T76: never; +type T77 = T extends T76 ? T76 : never; +type T78 = T extends T76 ? T76 : never; // Example from #21496 diff --git a/tests/baselines/reference/inferTypes1.symbols b/tests/baselines/reference/inferTypes1.symbols index e3772e89f01..1e5468e2b8e 100644 --- a/tests/baselines/reference/inferTypes1.symbols +++ b/tests/baselines/reference/inferTypes1.symbols @@ -378,7 +378,7 @@ type T76 = { x: T }; >x : Symbol(x, Decl(inferTypes1.ts, 82, 40)) >T : Symbol(T, Decl(inferTypes1.ts, 82, 9)) -type T77 = T extends T76 ? T76: never; +type T77 = T extends T76 ? T76 : never; >T77 : Symbol(T77, Decl(inferTypes1.ts, 82, 48)) >T : Symbol(T, Decl(inferTypes1.ts, 83, 9)) >T : Symbol(T, Decl(inferTypes1.ts, 83, 9)) @@ -389,154 +389,165 @@ type T77 = T extends T76 ? T76: never; >X : Symbol(X, Decl(inferTypes1.ts, 83, 33)) >Y : Symbol(Y, Decl(inferTypes1.ts, 83, 42)) +type T78 = T extends T76 ? T76 : never; +>T78 : Symbol(T78, Decl(inferTypes1.ts, 83, 66)) +>T : Symbol(T, Decl(inferTypes1.ts, 84, 9)) +>T : Symbol(T, Decl(inferTypes1.ts, 84, 9)) +>T76 : Symbol(T76, Decl(inferTypes1.ts, 80, 84)) +>X : Symbol(X, Decl(inferTypes1.ts, 84, 33), Decl(inferTypes1.ts, 84, 42)) +>X : Symbol(X, Decl(inferTypes1.ts, 84, 33), Decl(inferTypes1.ts, 84, 42)) +>T76 : Symbol(T76, Decl(inferTypes1.ts, 80, 84)) +>X : Symbol(X, Decl(inferTypes1.ts, 84, 33), Decl(inferTypes1.ts, 84, 42)) +>X : Symbol(X, Decl(inferTypes1.ts, 84, 33), Decl(inferTypes1.ts, 84, 42)) + // Example from #21496 type JsonifiedObject = { [K in keyof T]: Jsonified }; ->JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 83, 65)) ->T : Symbol(T, Decl(inferTypes1.ts, 87, 21)) ->K : Symbol(K, Decl(inferTypes1.ts, 87, 44)) ->T : Symbol(T, Decl(inferTypes1.ts, 87, 21)) ->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 87, 77)) ->T : Symbol(T, Decl(inferTypes1.ts, 87, 21)) ->K : Symbol(K, Decl(inferTypes1.ts, 87, 44)) +>JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 84, 66)) +>T : Symbol(T, Decl(inferTypes1.ts, 88, 21)) +>K : Symbol(K, Decl(inferTypes1.ts, 88, 44)) +>T : Symbol(T, Decl(inferTypes1.ts, 88, 21)) +>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 88, 77)) +>T : Symbol(T, Decl(inferTypes1.ts, 88, 21)) +>K : Symbol(K, Decl(inferTypes1.ts, 88, 44)) type Jsonified = ->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 87, 77)) ->T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) +>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 88, 77)) +>T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) T extends string | number | boolean | null ? T ->T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) ->T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) : T extends undefined | Function ? never // undefined and functions are removed ->T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) : T extends { toJSON(): infer R } ? R // toJSON is called if it exists (e.g. Date) ->T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) ->toJSON : Symbol(toJSON, Decl(inferTypes1.ts, 92, 17)) ->R : Symbol(R, Decl(inferTypes1.ts, 92, 33)) ->R : Symbol(R, Decl(inferTypes1.ts, 92, 33)) +>T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) +>toJSON : Symbol(toJSON, Decl(inferTypes1.ts, 93, 17)) +>R : Symbol(R, Decl(inferTypes1.ts, 93, 33)) +>R : Symbol(R, Decl(inferTypes1.ts, 93, 33)) : T extends object ? JsonifiedObject ->T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) ->JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 83, 65)) ->T : Symbol(T, Decl(inferTypes1.ts, 89, 15)) +>T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) +>JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 84, 66)) +>T : Symbol(T, Decl(inferTypes1.ts, 90, 15)) : "what is this"; type Example = { ->Example : Symbol(Example, Decl(inferTypes1.ts, 94, 21)) +>Example : Symbol(Example, Decl(inferTypes1.ts, 95, 21)) str: "literalstring", ->str : Symbol(str, Decl(inferTypes1.ts, 96, 16)) +>str : Symbol(str, Decl(inferTypes1.ts, 97, 16)) fn: () => void, ->fn : Symbol(fn, Decl(inferTypes1.ts, 97, 25)) +>fn : Symbol(fn, Decl(inferTypes1.ts, 98, 25)) date: Date, ->date : Symbol(date, Decl(inferTypes1.ts, 98, 19)) +>date : Symbol(date, Decl(inferTypes1.ts, 99, 19)) >Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) customClass: MyClass, ->customClass : Symbol(customClass, Decl(inferTypes1.ts, 99, 15)) ->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 106, 1)) +>customClass : Symbol(customClass, Decl(inferTypes1.ts, 100, 15)) +>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 107, 1)) obj: { ->obj : Symbol(obj, Decl(inferTypes1.ts, 100, 25)) +>obj : Symbol(obj, Decl(inferTypes1.ts, 101, 25)) prop: "property", ->prop : Symbol(prop, Decl(inferTypes1.ts, 101, 10)) +>prop : Symbol(prop, Decl(inferTypes1.ts, 102, 10)) clz: MyClass, ->clz : Symbol(clz, Decl(inferTypes1.ts, 102, 25)) ->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 106, 1)) +>clz : Symbol(clz, Decl(inferTypes1.ts, 103, 25)) +>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 107, 1)) nested: { attr: Date } ->nested : Symbol(nested, Decl(inferTypes1.ts, 103, 21)) ->attr : Symbol(attr, Decl(inferTypes1.ts, 104, 17)) +>nested : Symbol(nested, Decl(inferTypes1.ts, 104, 21)) +>attr : Symbol(attr, Decl(inferTypes1.ts, 105, 17)) >Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) }, } declare class MyClass { ->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 106, 1)) +>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 107, 1)) toJSON(): "correct"; ->toJSON : Symbol(MyClass.toJSON, Decl(inferTypes1.ts, 108, 23)) +>toJSON : Symbol(MyClass.toJSON, Decl(inferTypes1.ts, 109, 23)) } type JsonifiedExample = Jsonified; ->JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 110, 1)) ->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 87, 77)) ->Example : Symbol(Example, Decl(inferTypes1.ts, 94, 21)) +>JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 111, 1)) +>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 88, 77)) +>Example : Symbol(Example, Decl(inferTypes1.ts, 95, 21)) declare let ex: JsonifiedExample; ->ex : Symbol(ex, Decl(inferTypes1.ts, 113, 11)) ->JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 110, 1)) +>ex : Symbol(ex, Decl(inferTypes1.ts, 114, 11)) +>JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 111, 1)) const z1: "correct" = ex.customClass; ->z1 : Symbol(z1, Decl(inferTypes1.ts, 114, 5)) ->ex.customClass : Symbol(customClass, Decl(inferTypes1.ts, 99, 15)) ->ex : Symbol(ex, Decl(inferTypes1.ts, 113, 11)) ->customClass : Symbol(customClass, Decl(inferTypes1.ts, 99, 15)) +>z1 : Symbol(z1, Decl(inferTypes1.ts, 115, 5)) +>ex.customClass : Symbol(customClass, Decl(inferTypes1.ts, 100, 15)) +>ex : Symbol(ex, Decl(inferTypes1.ts, 114, 11)) +>customClass : Symbol(customClass, Decl(inferTypes1.ts, 100, 15)) const z2: string = ex.obj.nested.attr; ->z2 : Symbol(z2, Decl(inferTypes1.ts, 115, 5)) ->ex.obj.nested.attr : Symbol(attr, Decl(inferTypes1.ts, 104, 17)) ->ex.obj.nested : Symbol(nested, Decl(inferTypes1.ts, 103, 21)) ->ex.obj : Symbol(obj, Decl(inferTypes1.ts, 100, 25)) ->ex : Symbol(ex, Decl(inferTypes1.ts, 113, 11)) ->obj : Symbol(obj, Decl(inferTypes1.ts, 100, 25)) ->nested : Symbol(nested, Decl(inferTypes1.ts, 103, 21)) ->attr : Symbol(attr, Decl(inferTypes1.ts, 104, 17)) +>z2 : Symbol(z2, Decl(inferTypes1.ts, 116, 5)) +>ex.obj.nested.attr : Symbol(attr, Decl(inferTypes1.ts, 105, 17)) +>ex.obj.nested : Symbol(nested, Decl(inferTypes1.ts, 104, 21)) +>ex.obj : Symbol(obj, Decl(inferTypes1.ts, 101, 25)) +>ex : Symbol(ex, Decl(inferTypes1.ts, 114, 11)) +>obj : Symbol(obj, Decl(inferTypes1.ts, 101, 25)) +>nested : Symbol(nested, Decl(inferTypes1.ts, 104, 21)) +>attr : Symbol(attr, Decl(inferTypes1.ts, 105, 17)) // Repros from #21631 type A1> = [T, U]; ->A1 : Symbol(A1, Decl(inferTypes1.ts, 115, 38)) ->T : Symbol(T, Decl(inferTypes1.ts, 119, 8)) ->U : Symbol(U, Decl(inferTypes1.ts, 119, 10)) ->A1 : Symbol(A1, Decl(inferTypes1.ts, 115, 38)) ->T : Symbol(T, Decl(inferTypes1.ts, 119, 8)) ->U : Symbol(U, Decl(inferTypes1.ts, 119, 10)) +>A1 : Symbol(A1, Decl(inferTypes1.ts, 116, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 120, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 120, 10)) +>A1 : Symbol(A1, Decl(inferTypes1.ts, 116, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 120, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 120, 10)) type B1 = S extends A1 ? [T, U] : never; ->B1 : Symbol(B1, Decl(inferTypes1.ts, 119, 44)) ->S : Symbol(S, Decl(inferTypes1.ts, 120, 8)) ->S : Symbol(S, Decl(inferTypes1.ts, 120, 8)) ->A1 : Symbol(A1, Decl(inferTypes1.ts, 115, 38)) ->T : Symbol(T, Decl(inferTypes1.ts, 120, 31)) ->U : Symbol(U, Decl(inferTypes1.ts, 120, 40)) ->T : Symbol(T, Decl(inferTypes1.ts, 120, 31)) ->U : Symbol(U, Decl(inferTypes1.ts, 120, 40)) +>B1 : Symbol(B1, Decl(inferTypes1.ts, 120, 44)) +>S : Symbol(S, Decl(inferTypes1.ts, 121, 8)) +>S : Symbol(S, Decl(inferTypes1.ts, 121, 8)) +>A1 : Symbol(A1, Decl(inferTypes1.ts, 116, 38)) +>T : Symbol(T, Decl(inferTypes1.ts, 121, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 121, 40)) +>T : Symbol(T, Decl(inferTypes1.ts, 121, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 121, 40)) type A2 = [T, U]; ->A2 : Symbol(A2, Decl(inferTypes1.ts, 120, 61)) ->T : Symbol(T, Decl(inferTypes1.ts, 122, 8)) ->U : Symbol(U, Decl(inferTypes1.ts, 122, 10)) ->T : Symbol(T, Decl(inferTypes1.ts, 122, 8)) ->U : Symbol(U, Decl(inferTypes1.ts, 122, 10)) +>A2 : Symbol(A2, Decl(inferTypes1.ts, 121, 61)) +>T : Symbol(T, Decl(inferTypes1.ts, 123, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 123, 10)) +>T : Symbol(T, Decl(inferTypes1.ts, 123, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 123, 10)) type B2 = S extends A2 ? [T, U] : never; ->B2 : Symbol(B2, Decl(inferTypes1.ts, 122, 36)) ->S : Symbol(S, Decl(inferTypes1.ts, 123, 8)) ->S : Symbol(S, Decl(inferTypes1.ts, 123, 8)) ->A2 : Symbol(A2, Decl(inferTypes1.ts, 120, 61)) ->T : Symbol(T, Decl(inferTypes1.ts, 123, 31)) ->U : Symbol(U, Decl(inferTypes1.ts, 123, 40)) ->T : Symbol(T, Decl(inferTypes1.ts, 123, 31)) ->U : Symbol(U, Decl(inferTypes1.ts, 123, 40)) +>B2 : Symbol(B2, Decl(inferTypes1.ts, 123, 36)) +>S : Symbol(S, Decl(inferTypes1.ts, 124, 8)) +>S : Symbol(S, Decl(inferTypes1.ts, 124, 8)) +>A2 : Symbol(A2, Decl(inferTypes1.ts, 121, 61)) +>T : Symbol(T, Decl(inferTypes1.ts, 124, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 124, 40)) +>T : Symbol(T, Decl(inferTypes1.ts, 124, 31)) +>U : Symbol(U, Decl(inferTypes1.ts, 124, 40)) type C2 = S extends A2 ? [T, U] : never; ->C2 : Symbol(C2, Decl(inferTypes1.ts, 123, 61)) ->S : Symbol(S, Decl(inferTypes1.ts, 124, 8)) ->U : Symbol(U, Decl(inferTypes1.ts, 124, 10)) ->S : Symbol(S, Decl(inferTypes1.ts, 124, 8)) ->A2 : Symbol(A2, Decl(inferTypes1.ts, 120, 61)) ->T : Symbol(T, Decl(inferTypes1.ts, 124, 47)) ->U : Symbol(U, Decl(inferTypes1.ts, 124, 10)) ->T : Symbol(T, Decl(inferTypes1.ts, 124, 47)) ->U : Symbol(U, Decl(inferTypes1.ts, 124, 10)) +>C2 : Symbol(C2, Decl(inferTypes1.ts, 124, 61)) +>S : Symbol(S, Decl(inferTypes1.ts, 125, 8)) +>U : Symbol(U, Decl(inferTypes1.ts, 125, 10)) +>S : Symbol(S, Decl(inferTypes1.ts, 125, 8)) +>A2 : Symbol(A2, Decl(inferTypes1.ts, 121, 61)) +>T : Symbol(T, Decl(inferTypes1.ts, 125, 47)) +>U : Symbol(U, Decl(inferTypes1.ts, 125, 10)) +>T : Symbol(T, Decl(inferTypes1.ts, 125, 47)) +>U : Symbol(U, Decl(inferTypes1.ts, 125, 10)) diff --git a/tests/baselines/reference/inferTypes1.types b/tests/baselines/reference/inferTypes1.types index 4f050958773..ca60ea57d0e 100644 --- a/tests/baselines/reference/inferTypes1.types +++ b/tests/baselines/reference/inferTypes1.types @@ -384,7 +384,7 @@ type T76 = { x: T }; >x : T >T : T -type T77 = T extends T76 ? T76: never; +type T77 = T extends T76 ? T76 : never; >T77 : T77 >T : T >T : T @@ -395,6 +395,17 @@ type T77 = T extends T76 ? T76: never; >X : X >Y : Y +type T78 = T extends T76 ? T76 : never; +>T78 : T78 +>T : T +>T : T +>T76 : T76 +>X : X +>X : X +>T76 : T76 +>X : X +>X : X + // Example from #21496 type JsonifiedObject = { [K in keyof T]: Jsonified };