diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index a7e94da09d995..160211d19f120 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3358,6 +3358,7 @@ namespace ts { case SyntaxKind.TypeLiteral: case SyntaxKind.ArrayType: case SyntaxKind.TupleType: + case SyntaxKind.TypeSpread: case SyntaxKind.UnionType: case SyntaxKind.IntersectionType: case SyntaxKind.ParenthesizedType: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 82f41bc31e64c..c6d43db5d24db 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1,6 +1,9 @@ /// /// /// +/// + +declare var console: Console; /* @internal */ namespace ts { @@ -239,6 +242,7 @@ namespace ts { const intersectionTypes = createMap(); const literalTypes = createMap(); const indexedAccessTypes = createMap(); + const spreadTypes = createMap(); const evolvingArrayTypes: EvolvingArrayType[] = []; const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as __String); @@ -2542,6 +2546,10 @@ namespace ts { const indexTypeNode = typeToTypeNodeHelper((type).indexType, context); return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); } + if (type.flags & TypeFlags.TypeSpread) { + const typeNode = typeToTypeNodeHelper((type).type, context); + return createTypeSpread(typeNode); + } Debug.fail("Should be unreachable."); @@ -3305,6 +3313,10 @@ namespace ts { writeType((type).indexType, TypeFormatFlags.None); writePunctuation(writer, SyntaxKind.CloseBracketToken); } + else if (type.flags & TypeFlags.TypeSpread) { + writePunctuation(writer, SyntaxKind.DotDotDotToken); + writeType((type).type, TypeFormatFlags.None); + } else { // Should never get here // { ... } @@ -5392,6 +5404,7 @@ namespace ts { } function resolveObjectTypeMembers(type: ObjectType, source: InterfaceTypeWithDeclaredMembers, typeParameters: TypeParameter[], typeArguments: Type[]) { + if (allowSyntheticDefaultImports) console.log("resolveObjectTypeMembers", typeToString(type)); let mapper: TypeMapper; let members: SymbolTable; let callSignatures: Signature[]; @@ -6799,7 +6812,7 @@ namespace ts { const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgs, typeParameters, minTypeArgumentCount, node)); return createTypeReference(type, typeArguments); } - if (node.typeArguments) { + if (node.typeArguments && node.typeArguments.length) { error(node, Diagnostics.Type_0_is_not_generic, typeToString(type)); return unknownType; } @@ -6841,7 +6854,7 @@ namespace ts { } return getTypeAliasInstantiation(symbol, typeArguments); } - if (node.typeArguments) { + if (node.typeArguments && node.typeArguments.length) { error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol)); return unknownType; } @@ -6852,7 +6865,7 @@ namespace ts { * Get type from reference to named type that cannot be generic (enum or type parameter) */ function getTypeFromNonGenericTypeReference(node: TypeReferenceType, symbol: Symbol): Type { - if (node.typeArguments) { + if (node.typeArguments && node.typeArguments.length) { error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol)); return unknownType; } @@ -7218,11 +7231,69 @@ namespace ts { function getTypeFromTupleTypeNode(node: TupleTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNode)); + links.resolvedType = createTupleType(flatMap(node.elementTypes, getTypeFromTupleElement)); } return links.resolvedType; } + function getTypeSpreadTypes(tuple: Type): Type[] { + if (isGenericTupleType(tuple)) { + // Defer the operation by creating a spread type. + const id = "" + tuple.id; + let type = spreadTypes.get(id); + if (!type) { + spreadTypes.set(id, type = createTypeSpreadType(tuple)); + } + return [type]; + } + else { + // const type = getApparentType(nodeType); + if (allowSyntheticDefaultImports) { + console.log("type", typeToString(tuple)); + console.log("isTupleLikeType(type)", isTupleLikeType(tuple)); + } + if (isTupleLikeType(tuple)) { + // return map(getPropertiesOfType(tuple), getTypeOfSymbol); + return getTupleTypeElementTypes(tuple); + } + else { + // error(typeNode, Diagnostics.Tuple_type_spreads_may_only_be_created_from_tuple_types); + console.log("not a tuple, don't resolve?"); + return []; + } + } + } + + function isGenericTupleType(type: Type): boolean { + return type.flags & TypeFlags.TypeVariable ? true : + type.flags & TypeFlags.UnionOrIntersection ? forEach((type).types, isGenericTupleType) : + false; + } + + function getTupleTypeElementTypes(type: Type): Type[] { + Debug.assert(isTupleLikeType(type)); + const types = []; + let idx = 0; + let symbol: Symbol; + while (symbol = getPropertyOfObjectType(type, idx++ + "" as __String)) { + types.push(getTypeOfSymbol(symbol)); + } + return types; + } + + function getTypeFromTupleElement(node: TypeNode | TypeSpreadTypeNode): Type | Type[] { + if (node.kind === SyntaxKind.TypeSpread) { + const links = getNodeLinks(node); + if (!links.resolvedType) { + links.resolvedType = getTypeFromTypeNode((node as TypeSpreadTypeNode).type); + } + return getTypeSpreadTypes(links.resolvedType); + } + else { + return getTypeFromTypeNode(node as TypeNode); + } + } + interface TypeSet extends Array { containsAny?: boolean; containsUndefined?: boolean; @@ -7553,6 +7624,24 @@ namespace ts { return links.resolvedType; } + function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { + const fn = typeNodeToExpression(node.type); + const args = map(node.arguments, (type: TypeNode) => { + if (type.kind === SyntaxKind.TypeSpread) { + return createSpread(typeNodeToExpression((type as TypeSpreadTypeNode).type)); + } else { + return typeNodeToExpression(type); + } + }); + const callExpr = createCall(fn, node.typeArguments, args); + return checkExpression(callExpr); + } + + // null! as type + function typeNodeToExpression(type: TypeNode): Expression { + return createAsExpression(createNonNullExpression(createNull()), type); + } + function createIndexedAccessType(objectType: Type, indexType: Type) { const type = createType(TypeFlags.IndexedAccess); type.objectType = objectType; @@ -7560,6 +7649,13 @@ namespace ts { return type; } + function createTypeSpreadType(tuple: Type) { + console.log("createTypeSpreadType"); + const type = createType(TypeFlags.TypeSpread); + type.type = tuple; + return type; + } + function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode, cacheSymbol: boolean) { const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; const propName = indexType.flags & TypeFlags.StringOrNumberLiteral ? @@ -8010,6 +8106,8 @@ namespace ts { return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); case SyntaxKind.TypeOperator: return getTypeFromTypeOperatorNode(node); + case SyntaxKind.TypeCall: + return getTypeFromTypeCallNode(node); case SyntaxKind.IndexedAccessType: return getTypeFromIndexedAccessTypeNode(node); case SyntaxKind.MappedType: @@ -8375,6 +8473,9 @@ namespace ts { if (type.flags & TypeFlags.IndexedAccess) { return getIndexedAccessType(instantiateType((type).objectType, mapper), instantiateType((type).indexType, mapper)); } + // if (type.flags & TypeFlags.TypeSpread) { + // return getTypeSpreadTypes(instantiateType((type).type, mapper)); + // } return type; } @@ -13247,7 +13348,7 @@ namespace ts { return node.contextualType; } const parent = node.parent; - switch (parent.kind) { + switch (parent && parent.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.Parameter: case SyntaxKind.PropertyDeclaration: @@ -18782,7 +18883,7 @@ namespace ts { } const type = getTypeFromTypeReference(node); if (type !== unknownType) { - if (node.typeArguments) { + if (node.typeArguments && node.typeArguments.length) { // Do type argument local checks only if referenced type is successfully resolved forEach(node.typeArguments, checkSourceElement); if (produceDiagnostics) { @@ -18835,6 +18936,22 @@ namespace ts { forEach(node.elementTypes, checkSourceElement); } + function checkTypeSpreadTypeNode(node: TypeSpreadTypeNode) { + checkSourceElement(node.type); + // checkTypeSpreadType( getTypeFromTypeNode(node.type), node); + const type = getApparentType(getTypeFromTypeNode(node.type)); + if (!isArrayLikeType(type)) { // isTupleLikeType + grammarErrorOnNode(node, Diagnostics.Tuple_type_spreads_may_only_be_created_from_tuple_types); + } + } + + // function checkTypeSpreadType(spread: TypeSpreadType, node: TypeSpreadTypeNode) { + // const type = getApparentType(spread.type); + // if (!isArrayLikeType(type)) { // isTupleLikeType + // grammarErrorOnNode(node, Diagnostics.Tuple_type_spreads_may_only_be_created_from_tuple_types); + // } + // } + function checkUnionOrIntersectionType(node: UnionOrIntersectionTypeNode) { forEach(node.types, checkSourceElement); } @@ -22370,6 +22487,8 @@ namespace ts { return checkArrayType(node); case SyntaxKind.TupleType: return checkTupleType(node); + case SyntaxKind.TypeSpread: + return checkTypeSpreadTypeNode(node); case SyntaxKind.UnionType: case SyntaxKind.IntersectionType: return checkUnionOrIntersectionType(node); @@ -24338,7 +24457,7 @@ namespace ts { function checkGrammarTypeArguments(node: Node, typeArguments: NodeArray): boolean { return checkGrammarForDisallowedTrailingComma(typeArguments) || - checkGrammarForAtLeastOneTypeArgument(node, typeArguments); + false && checkGrammarForAtLeastOneTypeArgument(node, typeArguments); } function checkGrammarForOmittedArgument(args: NodeArray): boolean { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 8121f036ceabb..4a43ef26ea953 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2208,6 +2208,10 @@ "category": "Error", "code": 2713 }, + "Tuple type spreads may only be created from tuple types.": { + "category": "Error", + "code": 2714 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 5444c618353bd..1bb2ec4861a60 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -697,6 +697,8 @@ namespace ts { return emitShorthandPropertyAssignment(node); case SyntaxKind.SpreadAssignment: return emitSpreadAssignment(node as SpreadAssignment); + case SyntaxKind.TypeSpread: + return emitTypeSpread(node as TypeSpreadTypeNode); // Enum case SyntaxKind.EnumMember: @@ -753,6 +755,8 @@ namespace ts { return emitPropertyAccessExpression(node); case SyntaxKind.ElementAccessExpression: return emitElementAccessExpression(node); + case SyntaxKind.TypeCall: + return emitTypeCall(node); case SyntaxKind.CallExpression: return emitCallExpression(node); case SyntaxKind.NewExpression: @@ -1240,6 +1244,12 @@ namespace ts { write("]"); } + function emitTypeCall(node: TypeCallTypeNode) { + emit(node.type); + emitTypeArguments(node, node.typeArguments); + emitList(node, node.arguments, ListFormat.CallExpressionArguments); + } + function emitCallExpression(node: CallExpression) { emitExpression(node.expression); emitTypeArguments(node, node.typeArguments); @@ -2193,6 +2203,13 @@ namespace ts { } } + function emitTypeSpread(node: TypeSpreadTypeNode) { + if (node.type) { + write("..."); + emit(node.type); + } + } + // // Enum // diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index daec1bce1e8b5..2514c0d90aa76 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -888,6 +888,22 @@ namespace ts { : node; } + export function createTypeCall(type: TypeNode, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray) { + const node = createSynthesizedNode(SyntaxKind.TypeCall); + node.type = parenthesizeElementTypeMember(type); + node.typeArguments = asNodeArray(typeArguments); + node.arguments = parenthesizeElementTypeMembers(createNodeArray(argumentsArray)); + return node; + } + + export function updateTypeCall(node: TypeCallTypeNode, type: TypeNode, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray) { + return node.type !== type + || node.typeArguments !== typeArguments + || node.arguments !== argumentsArray + ? updateNode(createTypeCall(type, typeArguments, argumentsArray), node) + : node; + } + export function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray) { const node = createSynthesizedNode(SyntaxKind.CallExpression); node.expression = parenthesizeForAccess(expression); @@ -2185,6 +2201,19 @@ namespace ts { : node; } + export function createTypeSpread(type: TypeNode) { + console.log("createTypeSpread"); + const node = createSynthesizedNode(SyntaxKind.TypeSpread); + node.type = type !== undefined ? parenthesizeElementTypeMember(type) : undefined; + return node; + } + + export function updateTypeSpread(node: TypeSpreadTypeNode, type: TypeNode) { + return node.type !== type + ? updateNode(createTypeSpread(type), node) + : node; + } + // Enum export function createEnumMember(name: string | PropertyName, initializer?: Expression) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 7486c7541bed4..7c819727de264 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -85,6 +85,8 @@ namespace ts { visitNode(cbNode, (node).objectAssignmentInitializer); case SyntaxKind.SpreadAssignment: return visitNode(cbNode, (node).expression); + case SyntaxKind.TypeSpread: + return visitNode(cbNode, (node).type); case SyntaxKind.Parameter: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -170,6 +172,10 @@ namespace ts { case SyntaxKind.ElementAccessExpression: return visitNode(cbNode, (node).expression) || visitNode(cbNode, (node).argumentExpression); + case SyntaxKind.TypeCall: + return visitNode(cbNode, (node).type) || + visitNodes(cbNode, cbNodes, (node).typeArguments) || + visitNodes(cbNode, cbNodes, (node).arguments); case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: return visitNode(cbNode, (node).expression) || @@ -1378,8 +1384,9 @@ namespace ts { case ParsingContext.Parameters: return isStartOfParameter(); case ParsingContext.TypeArguments: - case ParsingContext.TupleElementTypes: return token() === SyntaxKind.CommaToken || isStartOfType(); + case ParsingContext.TupleElementTypes: + return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isStartOfType(); case ParsingContext.HeritageClauses: return isHeritageClause(); case ParsingContext.ImportOrExportSpecifiers: @@ -2585,7 +2592,7 @@ namespace ts { function parseTupleType(): TupleTypeNode { const node = createNode(SyntaxKind.TupleType); - node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); + node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElement, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); return finishNode(node); } @@ -2739,8 +2746,8 @@ namespace ts { return token() === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType(); } - function parseJSDocPostfixTypeOrHigher(): TypeNode { - const type = parseNonArrayType(); + function parseJSDocPostfixTypeOrHigher(typeNode?: TypeNode): TypeNode { + const type = typeNode || parseNonArrayType(); const kind = getKind(token()); if (!kind) return type; nextToken(); @@ -2762,8 +2769,8 @@ namespace ts { } } - function parseArrayTypeOrHigher(): TypeNode { - let type = parseJSDocPostfixTypeOrHigher(); + function parseArrayTypeOrHigher(typeNode?: TypeNode): TypeNode { + let type = parseJSDocPostfixTypeOrHigher(typeNode); while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { if (isStartOfType()) { const node = createNode(SyntaxKind.IndexedAccessType, type.pos); @@ -2795,7 +2802,7 @@ namespace ts { case SyntaxKind.KeyOfKeyword: return parseTypeOperator(SyntaxKind.KeyOfKeyword); } - return parseArrayTypeOrHigher(); + return parseTypeCallRest(); } function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode { @@ -4241,6 +4248,46 @@ namespace ts { } } + // type equivalent of parseCallExpressionRest + function parseTypeCallRest(type?: TypeNode): TypeNode { + while (true) { + type = parseArrayTypeOrHigher(type); + if (token() === SyntaxKind.LessThanToken) { + // See if this is the start of a generic invocation. If so, consume it and + // keep checking for postfix expressions. Otherwise, it's just a '<' that's + // part of an arithmetic expression. Break out so we consume it higher in the + // stack. + const typeArguments = tryParse(parseTypeArgumentsInExpression); + if (!typeArguments) { + return type; + } + + const callExpr = createNode(SyntaxKind.TypeCall, type.pos); + callExpr.type = type; + callExpr.typeArguments = typeArguments; + callExpr.arguments = parseTypeArgumentList(); + type = finishNode(callExpr); + continue; + } + else if (token() === SyntaxKind.OpenParenToken) { + const callExpr = createNode(SyntaxKind.TypeCall, type.pos); + callExpr.type = type; + callExpr.arguments = parseTypeArgumentList(); + type = finishNode(callExpr); + continue; + } + + return type; + } + } + + function parseTypeArgumentList() { + parseExpected(SyntaxKind.OpenParenToken); + const result = parseDelimitedList(ParsingContext.TypeArguments, parseTupleElement); + parseExpected(SyntaxKind.CloseParenToken); + return result; + } + function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression { while (true) { expression = parseMemberExpressionRest(expression); @@ -5161,6 +5208,19 @@ namespace ts { return finishNode(node); } + function parseTupleElement(): TypeSpreadTypeNode | TypeNode { + return (token() === SyntaxKind.DotDotDotToken) ? + parseTypeSpread() : + parseType(); + } + + function parseTypeSpread(): TypeSpreadTypeNode { + const node = createNode(SyntaxKind.TypeSpread); + parseExpected(SyntaxKind.DotDotDotToken); + node.type = parseTypeOperatorOrHigher(); + return finishNode(node); + } + function parseObjectBindingElement(): BindingElement { const node = createNode(SyntaxKind.BindingElement); node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8fe602ea6f94f..17e477ffd64c0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -240,6 +240,7 @@ namespace ts { IndexedAccessType, MappedType, LiteralType, + TypeCall, // Binding patterns ObjectBindingPattern, ArrayBindingPattern, @@ -343,6 +344,7 @@ namespace ts { PropertyAssignment, ShorthandPropertyAssignment, SpreadAssignment, + TypeSpread, // Enum EnumMember, @@ -398,7 +400,7 @@ namespace ts { FirstFutureReservedWord = ImplementsKeyword, LastFutureReservedWord = YieldKeyword, FirstTypeNode = TypePredicate, - LastTypeNode = LiteralType, + LastTypeNode = TypeCall, FirstPunctuation = OpenBraceToken, LastPunctuation = CaretEqualsToken, FirstToken = Unknown, @@ -950,7 +952,12 @@ namespace ts { export interface TupleTypeNode extends TypeNode { kind: SyntaxKind.TupleType; - elementTypes: NodeArray; + elementTypes: NodeArray; + } + + export interface TypeSpreadTypeNode extends TypeNode { + kind: SyntaxKind.TypeSpread; + type: TypeNode; } export type UnionOrIntersectionTypeNode = UnionTypeNode | IntersectionTypeNode; @@ -1495,6 +1502,13 @@ namespace ts { arguments: NodeArray; } + export interface TypeCallTypeNode extends TypeNode { + kind: SyntaxKind.TypeCall; + type: TypeNode; + typeArguments?: NodeArray; + arguments: NodeArray; + } + // see: https://tc39.github.io/ecma262/#prod-SuperCall export interface SuperCall extends CallExpression { expression: SuperExpression; @@ -3150,6 +3164,7 @@ namespace ts { NonPrimitive = 1 << 24, // intrinsic object type /* @internal */ JsxAttributes = 1 << 25, // Jsx attributes type + TypeSpread = 1 << 26, // spread in tuple types /* @internal */ Nullable = Undefined | Null, @@ -3398,6 +3413,11 @@ namespace ts { constraint?: Type; } + // type spread types (TypeFlags.TypeSpread) + export interface TypeSpreadType extends TypeVariable { + type: Type; + } + // keyof T types (TypeFlags.Index) export interface IndexType extends Type { type: TypeVariable | UnionOrIntersectionType; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f1a8dfd676b70..a979e1f06996e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4506,6 +4506,10 @@ namespace ts { return node.kind === SyntaxKind.SpreadAssignment; } + export function isTypeSpread(node: Node): node is TypeSpreadTypeNode { + return node.kind === SyntaxKind.TypeSpread; + } + // Enum export function isEnumMember(node: Node): node is EnumMember { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 1ce42199372d8..5203f775cd00e 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -446,6 +446,12 @@ namespace ts { visitNode((node).expression, visitor, isExpression), visitNode((node).argumentExpression, visitor, isExpression)); + case SyntaxKind.TypeCall: + return updateTypeCall(node, + visitNode((node).type, visitor, isTypeNode), + nodesVisitor((node).typeArguments, visitor, isTypeNode), + nodesVisitor((node).arguments, visitor, isTypeNode)); + case SyntaxKind.CallExpression: return updateCall(node, visitNode((node).expression, visitor, isExpression), @@ -869,6 +875,10 @@ namespace ts { return updateSpreadAssignment(node, visitNode((node).expression, visitor, isExpression)); + case SyntaxKind.TypeSpread: + return updateTypeSpread(node, + visitNode((node).type, visitor, isTypeNode)); + // Enum case SyntaxKind.EnumMember: return updateEnumMember(node, @@ -1391,6 +1401,14 @@ namespace ts { result = reduceNode((node).expression, cbNode, result); break; + case SyntaxKind.TypeCall: + result = reduceNode((node).type, cbNode, result); + break; + + case SyntaxKind.TypeSpread: + result = reduceNode((node).type, cbNode, result); + break; + // Enum case SyntaxKind.EnumMember: result = reduceNode((node).name, cbNode, result); diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt b/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt index 1c37f04be72b8..3479bd8044388 100644 --- a/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt +++ b/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt @@ -1,28 +1,16 @@ -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,5): error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,22): error TS1005: '=' expected. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,30): error TS1109: Expression expected. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,5): error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,22): error TS1005: '=' expected. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,32): error TS1109: Expression expected. +tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,30): error TS1005: '(' expected. +tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,32): error TS1005: '(' expected. -==== tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts (6 errors) ==== +==== tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts (2 errors) ==== // array type cannot use typeof. var x = 1; var xs: typeof x[]; // Not an error. This is equivalent to Array var xs2: typeof Array; var xs3: typeof Array; - ~~~ -!!! error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. - ~ -!!! error TS1005: '=' expected. ~ -!!! error TS1109: Expression expected. +!!! error TS1005: '(' expected. var xs4: typeof Array; - ~~~ -!!! error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. - ~ -!!! error TS1005: '=' expected. ~ -!!! error TS1109: Expression expected. \ No newline at end of file +!!! error TS1005: '(' expected. \ No newline at end of file diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.js b/tests/baselines/reference/arrayTypeOfTypeOf.js index f3653346be432..74a50b9cc1fc9 100644 --- a/tests/baselines/reference/arrayTypeOfTypeOf.js +++ b/tests/baselines/reference/arrayTypeOfTypeOf.js @@ -12,5 +12,5 @@ var xs4: typeof Array; var x = 1; var xs; // Not an error. This is equivalent to Array var xs2; -var xs3 = ; -var xs4 = ; +var xs3; +var xs4; diff --git a/tests/baselines/reference/invalidTypeOfTarget.errors.txt b/tests/baselines/reference/invalidTypeOfTarget.errors.txt index e658ab68c81bf..569c36d1f8552 100644 --- a/tests/baselines/reference/invalidTypeOfTarget.errors.txt +++ b/tests/baselines/reference/invalidTypeOfTarget.errors.txt @@ -1,6 +1,8 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(1,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,16): error TS1003: Identifier expected. -tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,24): error TS1005: '=>' expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,18): error TS1005: ',' expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,20): error TS1134: Variable declaration expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,24): error TS1109: Expression expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(3,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(4,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(5,16): error TS1003: Identifier expected. @@ -12,15 +14,19 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(8,16): error TS1003: Identifier expected. -==== tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts (12 errors) ==== +==== tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts (14 errors) ==== var x1: typeof {}; ~ !!! error TS1003: Identifier expected. var x2: typeof (): void; ~ !!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~~~~ +!!! error TS1134: Variable declaration expected. ~ -!!! error TS1005: '=>' expected. +!!! error TS1109: Expression expected. var x3: typeof 1; ~ !!! error TS1003: Identifier expected. diff --git a/tests/baselines/reference/invalidTypeOfTarget.js b/tests/baselines/reference/invalidTypeOfTarget.js index ebc5bb708757c..cda6f90a2f319 100644 --- a/tests/baselines/reference/invalidTypeOfTarget.js +++ b/tests/baselines/reference/invalidTypeOfTarget.js @@ -10,7 +10,8 @@ var x8: typeof /123/; //// [invalidTypeOfTarget.js] var x1 = {}; -var x2 = function () { return ; }; +var x2; +void ; var x3 = 1; var x4 = ''; var x5; diff --git a/tests/baselines/reference/overloadSelection.js b/tests/baselines/reference/overloadSelection.js new file mode 100644 index 0000000000000..a47f65ea88ac1 --- /dev/null +++ b/tests/baselines/reference/overloadSelection.js @@ -0,0 +1,12 @@ +//// [overloadSelection.ts] +interface Match { + (o: object): 0; + (o: any): 1; +} +type Wrap = (v: T) => Match(T); +type A = Wrap(RegExp); +// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) + + +//// [overloadSelection.js] +// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) diff --git a/tests/baselines/reference/overloadSelection.symbols b/tests/baselines/reference/overloadSelection.symbols new file mode 100644 index 0000000000000..fc3aa50564e30 --- /dev/null +++ b/tests/baselines/reference/overloadSelection.symbols @@ -0,0 +1,26 @@ +=== tests/cases/compiler/overloadSelection.ts === +interface Match { +>Match : Symbol(Match, Decl(overloadSelection.ts, 0, 0)) + + (o: object): 0; +>o : Symbol(o, Decl(overloadSelection.ts, 1, 3)) + + (o: any): 1; +>o : Symbol(o, Decl(overloadSelection.ts, 2, 3)) +} +type Wrap = (v: T) => Match(T); +>Wrap : Symbol(Wrap, Decl(overloadSelection.ts, 3, 1)) +>T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>v : Symbol(v, Decl(overloadSelection.ts, 4, 25)) +>T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) +>Match : Symbol(Match, Decl(overloadSelection.ts, 0, 0)) +>T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) + +type A = Wrap(RegExp); +>A : Symbol(A, Decl(overloadSelection.ts, 4, 43)) +>Wrap : Symbol(Wrap, Decl(overloadSelection.ts, 3, 1)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) + diff --git a/tests/baselines/reference/overloadSelection.types b/tests/baselines/reference/overloadSelection.types new file mode 100644 index 0000000000000..29bf2c3aa7a8d --- /dev/null +++ b/tests/baselines/reference/overloadSelection.types @@ -0,0 +1,26 @@ +=== tests/cases/compiler/overloadSelection.ts === +interface Match { +>Match : Match + + (o: object): 0; +>o : object + + (o: any): 1; +>o : any +} +type Wrap = (v: T) => Match(T); +>Wrap : Wrap +>T : T +>RegExp : RegExp +>v : T +>T : T +>Match : Match +>T : T + +type A = Wrap(RegExp); +>A : 1 +>Wrap : Wrap +>RegExp : RegExp + +// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) + diff --git a/tests/baselines/reference/parserObjectType5.errors.txt b/tests/baselines/reference/parserObjectType5.errors.txt index d4db1d2d85c51..2b21a42ecf243 100644 --- a/tests/baselines/reference/parserObjectType5.errors.txt +++ b/tests/baselines/reference/parserObjectType5.errors.txt @@ -1,13 +1,16 @@ tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(2,7): error TS2304: Cannot find name 'B'. +tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(3,5): error TS2304: Cannot find name 'T'. tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(3,7): error TS1005: '(' expected. -==== tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts (3 errors) ==== var v: { A: B ~ !!! error TS2304: Cannot find name 'B'. ; + ~ +!!! error TS2304: Cannot find name 'T'. ~ !!! error TS1005: '(' expected. }; \ No newline at end of file diff --git a/tests/baselines/reference/parserTypeQuery8.errors.txt b/tests/baselines/reference/parserTypeQuery8.errors.txt index 4a7098ea8fd3f..40c51093d140a 100644 --- a/tests/baselines/reference/parserTypeQuery8.errors.txt +++ b/tests/baselines/reference/parserTypeQuery8.errors.txt @@ -1,16 +1,13 @@ tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,15): error TS2304: Cannot find name 'A'. -tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,16): error TS1005: '=' expected. tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,17): error TS2304: Cannot find name 'B'. -tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,19): error TS1109: Expression expected. +tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,19): error TS1005: '(' expected. -==== tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts (4 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts (3 errors) ==== var v: typeof A ~ !!! error TS2304: Cannot find name 'A'. - ~ -!!! error TS1005: '=' expected. ~ !!! error TS2304: Cannot find name 'B'. -!!! error TS1109: Expression expected. \ No newline at end of file +!!! error TS1005: '(' expected. \ No newline at end of file diff --git a/tests/baselines/reference/parserTypeQuery8.js b/tests/baselines/reference/parserTypeQuery8.js index 995ad013c1f0d..f0fd7d6212e76 100644 --- a/tests/baselines/reference/parserTypeQuery8.js +++ b/tests/baselines/reference/parserTypeQuery8.js @@ -2,4 +2,4 @@ var v: typeof A //// [parserTypeQuery8.js] -var v = ; +var v; diff --git a/tests/baselines/reference/tupleTypeSpread.js b/tests/baselines/reference/tupleTypeSpread.js new file mode 100644 index 0000000000000..d7751fd4f5db2 --- /dev/null +++ b/tests/baselines/reference/tupleTypeSpread.js @@ -0,0 +1,7 @@ +//// [tupleTypeSpread.ts] +type a = [1, ...[2]]; +type Combine = [Head, ...Tail]; +type b = Combine<1, [2, 3]>; + + +//// [tupleTypeSpread.js] diff --git a/tests/baselines/reference/tupleTypeSpread.symbols b/tests/baselines/reference/tupleTypeSpread.symbols new file mode 100644 index 0000000000000..303808d580702 --- /dev/null +++ b/tests/baselines/reference/tupleTypeSpread.symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/tupleTypeSpread.ts === +type a = [1, ...[2]]; +>a : Symbol(a, Decl(tupleTypeSpread.ts, 0, 0)) + +type Combine = [Head, ...Tail]; +>Combine : Symbol(Combine, Decl(tupleTypeSpread.ts, 0, 21)) +>Head : Symbol(Head, Decl(tupleTypeSpread.ts, 1, 13)) +>Tail : Symbol(Tail, Decl(tupleTypeSpread.ts, 1, 18)) +>Head : Symbol(Head, Decl(tupleTypeSpread.ts, 1, 13)) +>Tail : Symbol(Tail, Decl(tupleTypeSpread.ts, 1, 18)) + +type b = Combine<1, [2, 3]>; +>b : Symbol(b, Decl(tupleTypeSpread.ts, 1, 57)) +>Combine : Symbol(Combine, Decl(tupleTypeSpread.ts, 0, 21)) + diff --git a/tests/baselines/reference/tupleTypeSpread.types b/tests/baselines/reference/tupleTypeSpread.types new file mode 100644 index 0000000000000..a804885e1a591 --- /dev/null +++ b/tests/baselines/reference/tupleTypeSpread.types @@ -0,0 +1,15 @@ +=== tests/cases/compiler/tupleTypeSpread.ts === +type a = [1, ...[2]]; +>a : [1, 2] + +type Combine = [Head, ...Tail]; +>Combine : [Head, ...Tail] +>Head : Head +>Tail : Tail +>Head : Head +>Tail : Tail + +type b = Combine<1, [2, 3]>; +>b : [1, ...Tail] +>Combine : [Head, ...Tail] + diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js new file mode 100644 index 0000000000000..36baf427ab212 --- /dev/null +++ b/tests/baselines/reference/typeCall.js @@ -0,0 +1,69 @@ +//// [typeCall.ts] +type F1 = () => 1; +type a = F1(); + +type F2 = (a: string) => 1; +type b = F2('foo'); + +interface F3 { + (): 1; + (a: number): 2; + (a: string): 3; +} +type c = F3(); +type d = F3(123); +type e = F3('foo'); + +declare function f4(a: string): 1; +let a = 'foo'; +type f = typeof f4(typeof a); + +type g = (() => 1)(); + +type Id = (v: T) => T; +type h = Id(123); + +type Wrap = Id(T); +type i = Wrap<123>; + +type F5 = () => () => { a: () => 1; }; +type j = F5()()['a'](); + +type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +type k2 = Id<>('foo'); // ok, `string` + +declare function id(v: T): T; +let l = id('foo'); + +interface IsPrimitive { + (o: object): '0'; + (o: any): '1'; +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok + +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +type genericIsPrimitive = () => IsPrimitive(T); +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +type regexpIsPrimitive2 = genericIsPrimitive<>(); +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); + +// binary function composition, still fails +type Fn1 = (v: T[]) => { [k: string]: T }; +type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; +type Fn3 = (v: T) => Fn2(Fn1(T)); +type Fn4 = Fn3(1); + + +//// [typeCall.js] +var a = 'foo'; +var l = id('foo'); diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols new file mode 100644 index 0000000000000..50e4cde6189a1 --- /dev/null +++ b/tests/baselines/reference/typeCall.symbols @@ -0,0 +1,213 @@ +=== tests/cases/compiler/typeCall.ts === +type F1 = () => 1; +>F1 : Symbol(F1, Decl(typeCall.ts, 0, 0)) + +type a = F1(); +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) +>F1 : Symbol(F1, Decl(typeCall.ts, 0, 0)) + +type F2 = (a: string) => 1; +>F2 : Symbol(F2, Decl(typeCall.ts, 1, 14)) +>a : Symbol(a, Decl(typeCall.ts, 3, 11)) + +type b = F2('foo'); +>b : Symbol(b, Decl(typeCall.ts, 3, 27)) +>F2 : Symbol(F2, Decl(typeCall.ts, 1, 14)) + +interface F3 { +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + + (): 1; + (a: number): 2; +>a : Symbol(a, Decl(typeCall.ts, 8, 5)) + + (a: string): 3; +>a : Symbol(a, Decl(typeCall.ts, 9, 5)) +} +type c = F3(); +>c : Symbol(c, Decl(typeCall.ts, 10, 1)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + +type d = F3(123); +>d : Symbol(d, Decl(typeCall.ts, 11, 14)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + +type e = F3('foo'); +>e : Symbol(e, Decl(typeCall.ts, 12, 17)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + +declare function f4(a: string): 1; +>f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) +>a : Symbol(a, Decl(typeCall.ts, 15, 20)) + +let a = 'foo'; +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) + +type f = typeof f4(typeof a); +>f : Symbol(f, Decl(typeCall.ts, 16, 14)) +>f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) + +type g = (() => 1)(); +>g : Symbol(g, Decl(typeCall.ts, 17, 29)) + +type Id = (v: T) => T; +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) +>v : Symbol(v, Decl(typeCall.ts, 21, 14)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) + +type h = Id(123); +>h : Symbol(h, Decl(typeCall.ts, 21, 25)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) + +type Wrap = Id(T); +>Wrap : Symbol(Wrap, Decl(typeCall.ts, 22, 17)) +>T : Symbol(T, Decl(typeCall.ts, 24, 10)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) +>T : Symbol(T, Decl(typeCall.ts, 24, 10)) + +type i = Wrap<123>; +>i : Symbol(i, Decl(typeCall.ts, 24, 21)) +>Wrap : Symbol(Wrap, Decl(typeCall.ts, 22, 17)) + +type F5 = () => () => { a: () => 1; }; +>F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) +>a : Symbol(a, Decl(typeCall.ts, 27, 23)) + +type j = F5()()['a'](); +>j : Symbol(j, Decl(typeCall.ts, 27, 38)) +>F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) + +type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +>k1 : Symbol(k1, Decl(typeCall.ts, 28, 23)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) + +type k2 = Id<>('foo'); // ok, `string` +>k2 : Symbol(k2, Decl(typeCall.ts, 30, 28)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) + +declare function id(v: T): T; +>id : Symbol(id, Decl(typeCall.ts, 31, 30)) +>T : Symbol(T, Decl(typeCall.ts, 33, 20)) +>v : Symbol(v, Decl(typeCall.ts, 33, 23)) +>T : Symbol(T, Decl(typeCall.ts, 33, 20)) +>T : Symbol(T, Decl(typeCall.ts, 33, 20)) + +let l = id('foo'); +>l : Symbol(l, Decl(typeCall.ts, 34, 3)) +>id : Symbol(id, Decl(typeCall.ts, 31, 30)) + +interface IsPrimitive { +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) + + (o: object): '0'; +>o : Symbol(o, Decl(typeCall.ts, 37, 3)) + + (o: any): '1'; +>o : Symbol(o, Decl(typeCall.ts, 38, 3)) +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +>stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 39, 1)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) + +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +>regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 40, 45)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +type genericIsPrimitive = () => IsPrimitive(T); +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 41, 45)) +>T : Symbol(T, Decl(typeCall.ts, 44, 27)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) +>T : Symbol(T, Decl(typeCall.ts, 44, 27)) + +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +>stringIsPrimitive2 : Symbol(stringIsPrimitive2, Decl(typeCall.ts, 44, 50)) +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 41, 45)) + +type regexpIsPrimitive2 = genericIsPrimitive<>(); +>regexpIsPrimitive2 : Symbol(regexpIsPrimitive2, Decl(typeCall.ts, 45, 57)) +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 41, 45)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 46, 57)) +>T : Symbol(T, Decl(typeCall.ts, 50, 28)) +>v : Symbol(v, Decl(typeCall.ts, 50, 31)) +>T : Symbol(T, Decl(typeCall.ts, 50, 28)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) +>T : Symbol(T, Decl(typeCall.ts, 50, 28)) + +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +>stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 50, 55)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 46, 57)) + +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +>regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 51, 54)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 46, 57)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +>map : Symbol(map, Decl(typeCall.ts, 52, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 55, 12)) +>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>O : Symbol(O, Decl(typeCall.ts, 55, 32)) +>fn : Symbol(fn, Decl(typeCall.ts, 55, 51)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 55, 12)) +>obj : Symbol(obj, Decl(typeCall.ts, 55, 58)) +>O : Symbol(O, Decl(typeCall.ts, 55, 32)) +>P : Symbol(P, Decl(typeCall.ts, 55, 73)) +>O : Symbol(O, Decl(typeCall.ts, 55, 32)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 55, 12)) +>P : Symbol(P, Decl(typeCall.ts, 55, 73)) + +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +>z : Symbol(z, Decl(typeCall.ts, 55, 96)) +>map : Symbol(map, Decl(typeCall.ts, 52, 53)) +>T : Symbol(T, Decl(typeCall.ts, 56, 14)) +>v : Symbol(v, Decl(typeCall.ts, 56, 17)) +>T : Symbol(T, Decl(typeCall.ts, 56, 14)) +>T : Symbol(T, Decl(typeCall.ts, 56, 14)) +>a : Symbol(a, Decl(typeCall.ts, 56, 32)) +>b : Symbol(b, Decl(typeCall.ts, 56, 38)) +>c : Symbol(c, Decl(typeCall.ts, 56, 44)) + +// binary function composition, still fails +type Fn1 = (v: T[]) => { [k: string]: T }; +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 56, 53)) +>T : Symbol(T, Decl(typeCall.ts, 59, 9)) +>v : Symbol(v, Decl(typeCall.ts, 59, 30)) +>T : Symbol(T, Decl(typeCall.ts, 59, 9)) +>k : Symbol(k, Decl(typeCall.ts, 59, 44)) +>T : Symbol(T, Decl(typeCall.ts, 59, 9)) + +type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 59, 60)) +>T : Symbol(T, Decl(typeCall.ts, 60, 9)) +>v : Symbol(v, Decl(typeCall.ts, 60, 15)) +>k : Symbol(k, Decl(typeCall.ts, 60, 21)) +>T : Symbol(T, Decl(typeCall.ts, 60, 9)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(typeCall.ts, 60, 9)) + +type Fn3 = (v: T) => Fn2(Fn1(T)); +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 60, 58)) +>T : Symbol(T, Decl(typeCall.ts, 61, 9)) +>v : Symbol(v, Decl(typeCall.ts, 61, 15)) +>T : Symbol(T, Decl(typeCall.ts, 61, 9)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 59, 60)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 56, 53)) +>T : Symbol(T, Decl(typeCall.ts, 61, 9)) + +type Fn4 = Fn3(1); +>Fn4 : Symbol(Fn4, Decl(typeCall.ts, 61, 36)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 60, 58)) + diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types new file mode 100644 index 0000000000000..4c65d69645786 --- /dev/null +++ b/tests/baselines/reference/typeCall.types @@ -0,0 +1,216 @@ +=== tests/cases/compiler/typeCall.ts === +type F1 = () => 1; +>F1 : F1 + +type a = F1(); +>a : 1 +>F1 : F1 + +type F2 = (a: string) => 1; +>F2 : F2 +>a : string + +type b = F2('foo'); +>b : 1 +>F2 : F2 + +interface F3 { +>F3 : F3 + + (): 1; + (a: number): 2; +>a : number + + (a: string): 3; +>a : string +} +type c = F3(); +>c : 1 +>F3 : F3 + +type d = F3(123); +>d : 2 +>F3 : F3 + +type e = F3('foo'); +>e : 3 +>F3 : F3 + +declare function f4(a: string): 1; +>f4 : (a: string) => 1 +>a : string + +let a = 'foo'; +>a : string +>'foo' : "foo" + +type f = typeof f4(typeof a); +>f : 1 +>f4 : (a: string) => 1 +>a : string + +type g = (() => 1)(); +>g : 1 + +type Id = (v: T) => T; +>Id : Id +>T : T +>v : T +>T : T +>T : T + +type h = Id(123); +>h : 123 +>Id : Id + +type Wrap = Id(T); +>Wrap : T +>T : T +>Id : Id +>T : T + +type i = Wrap<123>; +>i : 123 +>Wrap : T + +type F5 = () => () => { a: () => 1; }; +>F5 : F5 +>a : () => 1 + +type j = F5()()['a'](); +>j : 1 +>F5 : F5 + +type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +>k1 : any +>Id : Id + +type k2 = Id<>('foo'); // ok, `string` +>k2 : string +>Id : Id + +declare function id(v: T): T; +>id : (v: T) => T +>T : T +>v : T +>T : T +>T : T + +let l = id('foo'); +>l : string +>id('foo') : string +>id : (v: T) => T +>'foo' : "foo" + +interface IsPrimitive { +>IsPrimitive : IsPrimitive + + (o: object): '0'; +>o : object + + (o: any): '1'; +>o : any +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +>stringIsPrimitive : "1" +>IsPrimitive : IsPrimitive + +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +>regexpIsPrimitive : "1" +>IsPrimitive : IsPrimitive +>RegExp : RegExp + +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +type genericIsPrimitive = () => IsPrimitive(T); +>genericIsPrimitive : genericIsPrimitive +>T : T +>IsPrimitive : IsPrimitive +>T : T + +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +>stringIsPrimitive2 : "1" +>genericIsPrimitive : genericIsPrimitive + +type regexpIsPrimitive2 = genericIsPrimitive<>(); +>regexpIsPrimitive2 : "1" +>genericIsPrimitive : genericIsPrimitive +>RegExp : RegExp + +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +>genericIsPrimitive3 : genericIsPrimitive3 +>T : T +>v : T +>T : T +>IsPrimitive : IsPrimitive +>T : T + +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +>stringIsPrimitive3 : "1" +>genericIsPrimitive3 : genericIsPrimitive3 + +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +>regexpIsPrimitive3 : "1" +>genericIsPrimitive3 : genericIsPrimitive3 +>RegExp : RegExp + +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +>map : map +>Fn : Fn +>Function : Function +>O : O +>fn : Fn +>Fn : Fn +>obj : O +>O : O +>P : P +>O : O +>Fn : Fn +>P : P + +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +>z : { a: any; b: any; c: any; } +>map : map +>T : T +>v : T +>T : T +>T : T +>a : 1 +>b : 2 +>c : 3 + +// binary function composition, still fails +type Fn1 = (v: T[]) => { [k: string]: T }; +>Fn1 : Fn1 +>T : T +>v : T[] +>T : T +>k : string +>T : T + +type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; +>Fn2 : Fn2 +>T : T +>v : { [k: string]: T; } +>k : string +>T : T +>ReadonlyArray : ReadonlyArray +>T : T + +type Fn3 = (v: T) => Fn2(Fn1(T)); +>Fn3 : Fn3 +>T : T +>v : T +>T : T +>Fn2 : Fn2 +>Fn1 : Fn1 +>T : T + +type Fn4 = Fn3(1); +>Fn4 : any +>Fn3 : Fn3 + diff --git a/tests/baselines/reference/typeCallSpreads.errors.txt b/tests/baselines/reference/typeCallSpreads.errors.txt new file mode 100644 index 0000000000000..78aed3b1c8f0c --- /dev/null +++ b/tests/baselines/reference/typeCallSpreads.errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/typeCallSpreads.ts(2,13): error TS1005: ')' expected. +tests/cases/compiler/typeCallSpreads.ts(2,19): error TS1005: ';' expected. + + +==== tests/cases/compiler/typeCallSpreads.ts (2 errors) ==== + type Fn = (v: T) => T; + type a = Fn(...[1]); + ~~~ +!!! error TS1005: ')' expected. + ~ +!!! error TS1005: ';' expected. + \ No newline at end of file diff --git a/tests/baselines/reference/typeCallSpreads.js b/tests/baselines/reference/typeCallSpreads.js new file mode 100644 index 0000000000000..d89672c327404 --- /dev/null +++ b/tests/baselines/reference/typeCallSpreads.js @@ -0,0 +1,8 @@ +//// [typeCallSpreads.ts] +type Fn = (v: T) => T; +type a = Fn(...[1]); + + +//// [typeCallSpreads.js] +[1]; +; diff --git a/tests/cases/compiler/overloadSelection.ts b/tests/cases/compiler/overloadSelection.ts new file mode 100644 index 0000000000000..06b5019fd53fb --- /dev/null +++ b/tests/cases/compiler/overloadSelection.ts @@ -0,0 +1,9 @@ +// @allowSyntheticDefaultImports: true + +interface Match { + (o: object): 0; + (o: any): 1; +} +type Wrap = (v: T) => Match(T); +type A = Wrap(RegExp); +// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) diff --git a/tests/cases/compiler/tupleTypeSpread.ts b/tests/cases/compiler/tupleTypeSpread.ts new file mode 100644 index 0000000000000..a2693a8f9f4af --- /dev/null +++ b/tests/cases/compiler/tupleTypeSpread.ts @@ -0,0 +1,4 @@ +// @allowSyntheticDefaultImports: true +type a = [1, ...[2]]; +type Combine = [Head, ...Tail]; +type b = Combine<1, [2, 3]>; diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts new file mode 100644 index 0000000000000..db803444ed8d6 --- /dev/null +++ b/tests/cases/compiler/typeCall.ts @@ -0,0 +1,65 @@ +// @allowSyntheticDefaultImports: true + +type F1 = () => 1; +type a = F1(); + +type F2 = (a: string) => 1; +type b = F2('foo'); + +interface F3 { + (): 1; + (a: number): 2; + (a: string): 3; +} +type c = F3(); +type d = F3(123); +type e = F3('foo'); + +declare function f4(a: string): 1; +let a = 'foo'; +type f = typeof f4(typeof a); + +type g = (() => 1)(); + +type Id = (v: T) => T; +type h = Id(123); + +type Wrap = Id(T); +type i = Wrap<123>; + +type F5 = () => () => { a: () => 1; }; +type j = F5()()['a'](); + +type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +type k2 = Id<>('foo'); // ok, `string` + +declare function id(v: T): T; +let l = id('foo'); + +interface IsPrimitive { + (o: object): '0'; + (o: any): '1'; +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok + +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +type genericIsPrimitive = () => IsPrimitive(T); +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +type regexpIsPrimitive2 = genericIsPrimitive<>(); +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); + +// binary function composition, still fails +type Fn1 = (v: T[]) => { [k: string]: T }; +type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; +type Fn3 = (v: T) => Fn2(Fn1(T)); +type Fn4 = Fn3(1); diff --git a/tests/cases/compiler/typeCallSpreads.ts b/tests/cases/compiler/typeCallSpreads.ts new file mode 100644 index 0000000000000..c49622b419927 --- /dev/null +++ b/tests/cases/compiler/typeCallSpreads.ts @@ -0,0 +1,2 @@ +type Fn = (v: T) => T; +type a = Fn(...[1]);