diff --git a/Gulpfile.ts b/Gulpfile.ts index 32fbf2c43e..03046789fe 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -935,7 +935,7 @@ gulp.task(loggedIOJsPath, /*help*/ false, [], (done) => { const temp = path.join(builtLocalDirectory, "temp"); mkdirP(temp, (err) => { if (err) { console.error(err); done(err); process.exit(1); } - exec(host, [LKGCompiler, "--types --outdir", temp, loggedIOpath], () => { + exec(host, [LKGCompiler, "--types", "--target es5", "--lib es5", "--outdir", temp, loggedIOpath], () => { fs.renameSync(path.join(temp, "/harness/loggedIO.js"), loggedIOJsPath); del(temp).then(() => done(), done); }, done); @@ -946,7 +946,13 @@ const instrumenterPath = path.join(harnessDirectory, "instrumenter.ts"); const instrumenterJsPath = path.join(builtLocalDirectory, "instrumenter.js"); gulp.task(instrumenterJsPath, /*help*/ false, [servicesFile], () => { const settings: tsc.Settings = getCompilerSettings({ - outFile: instrumenterJsPath + outFile: instrumenterJsPath, + target: "es5", + lib: [ + "es6", + "dom", + "scripthost" + ] }, /*useBuiltCompiler*/ true); return gulp.src(instrumenterPath) .pipe(newer(instrumenterJsPath)) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index b6074162ff..1940231a6d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -149,7 +149,7 @@ namespace ts { inStrictMode = bindInStrictMode(file, opts); classifiableNames = createMap(); symbolCount = 0; - skipTransformFlagAggregation = isDeclarationFile(file); + skipTransformFlagAggregation = file.isDeclarationFile; Symbol = objectAllocator.getSymbolConstructor(); @@ -182,7 +182,7 @@ namespace ts { return bindSourceFile; function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean { - if ((opts.alwaysStrict === undefined ? opts.strict : opts.alwaysStrict) && !isDeclarationFile(file)) { + if ((opts.alwaysStrict === undefined ? opts.strict : opts.alwaysStrict) && !file.isDeclarationFile) { // bind in strict mode source files with alwaysStrict option return true; } @@ -2527,7 +2527,7 @@ namespace ts { } function bindFunctionDeclaration(node: FunctionDeclaration) { - if (!isDeclarationFile(file) && !isInAmbientContext(node)) { + if (!file.isDeclarationFile && !isInAmbientContext(node)) { if (isAsyncFunction(node)) { emitFlags |= NodeFlags.HasAsyncFunctions; } @@ -2544,7 +2544,7 @@ namespace ts { } function bindFunctionExpression(node: FunctionExpression) { - if (!isDeclarationFile(file) && !isInAmbientContext(node)) { + if (!file.isDeclarationFile && !isInAmbientContext(node)) { if (isAsyncFunction(node)) { emitFlags |= NodeFlags.HasAsyncFunctions; } @@ -2558,7 +2558,7 @@ namespace ts { } function bindPropertyOrMethodOrAccessor(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { - if (!isDeclarationFile(file) && !isInAmbientContext(node)) { + if (!file.isDeclarationFile && !isInAmbientContext(node)) { if (isAsyncFunction(node)) { emitFlags |= NodeFlags.HasAsyncFunctions; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 62c8934620..12f6e3e579 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -47,6 +47,7 @@ namespace ts { let typeCount = 0; let symbolCount = 0; + let enumCount = 0; let symbolInstantiationDepth = 0; const emptyArray: any[] = []; @@ -214,8 +215,7 @@ namespace ts { const tupleTypes: GenericType[] = []; const unionTypes = createMap(); const intersectionTypes = createMap(); - const stringLiteralTypes = createMap(); - const numericLiteralTypes = createMap(); + const literalTypes = createMap(); const indexedAccessTypes = createMap(); const evolvingArrayTypes: EvolvingArrayType[] = []; @@ -313,8 +313,8 @@ namespace ts { let flowLoopCount = 0; let visitedFlowCount = 0; - const emptyStringType = getLiteralTypeForText(TypeFlags.StringLiteral, ""); - const zeroType = getLiteralTypeForText(TypeFlags.NumberLiteral, "0"); + const emptyStringType = getLiteralType(""); + const zeroType = getLiteralType(0); const resolutionTargets: TypeSystemEntity[] = []; const resolutionResults: boolean[] = []; @@ -1300,7 +1300,7 @@ namespace ts { return node; } - return findAncestor(node, n => n.kind === SyntaxKind.ImportDeclaration) as ImportDeclaration; + return findAncestor(node, isImportDeclaration); } } @@ -1903,7 +1903,7 @@ namespace ts { } function createTypeofType() { - return getUnionType(convertToArray(typeofEQFacts.keys(), s => getLiteralTypeForText(TypeFlags.StringLiteral, s))); + return getUnionType(convertToArray(typeofEQFacts.keys(), getLiteralType)); } // A reserved member name starts with two underscores, but the third character cannot be an underscore @@ -2275,48 +2275,74 @@ namespace ts { } function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string { - const writer = getSingleLineStringWriter(); - getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); - let result = writer.string(); - releaseStringWriter(writer); + const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName); + Debug.assert(typeNode !== undefined, "should always get typenode?"); + const options = { removeComments: true }; + const writer = createTextWriter(""); + const printer = createPrinter(options, writer); + const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); + printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer); + const result = writer.getText(); const maxLength = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation ? undefined : 100; if (maxLength && result.length >= maxLength) { - result = result.substr(0, maxLength - "...".length) + "..."; + return result.substr(0, maxLength - "...".length) + "..."; } return result; + + function toNodeBuilderFlags(flags?: TypeFormatFlags): NodeBuilderFlags { + let result = NodeBuilderFlags.None; + if (!flags) { + return result; + } + if (flags & TypeFormatFlags.NoTruncation) { + result |= NodeBuilderFlags.NoTruncation; + } + if (flags & TypeFormatFlags.UseFullyQualifiedType) { + result |= NodeBuilderFlags.UseFullyQualifiedType; + } + if (flags & TypeFormatFlags.SuppressAnyReturnType) { + result |= NodeBuilderFlags.SuppressAnyReturnType; + } + if (flags & TypeFormatFlags.WriteArrayAsGenericType) { + result |= NodeBuilderFlags.WriteArrayAsGenericType; + } + if (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature) { + result |= NodeBuilderFlags.WriteTypeArgumentsOfSignature; + } + + return result; + } } function createNodeBuilder() { - let context: NodeBuilderContext; - return { typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => { - context = createNodeBuilderContext(enclosingDeclaration, flags); - const resultingNode = typeToTypeNodeHelper(type); + const context = createNodeBuilderContext(enclosingDeclaration, flags); + const resultingNode = typeToTypeNodeHelper(type, context); const result = context.encounteredError ? undefined : resultingNode; return result; }, indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => { - context = createNodeBuilderContext(enclosingDeclaration, flags); - const resultingNode = indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind); + const context = createNodeBuilderContext(enclosingDeclaration, flags); + const resultingNode = indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind, context); const result = context.encounteredError ? undefined : resultingNode; return result; }, signatureToSignatureDeclaration: (signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => { - context = createNodeBuilderContext(enclosingDeclaration, flags); - const resultingNode = signatureToSignatureDeclarationHelper(signature, kind); + const context = createNodeBuilderContext(enclosingDeclaration, flags); + const resultingNode = signatureToSignatureDeclarationHelper(signature, kind, context); const result = context.encounteredError ? undefined : resultingNode; return result; } }; interface NodeBuilderContext { - readonly enclosingDeclaration: Node | undefined; - readonly flags: NodeBuilderFlags | undefined; + enclosingDeclaration: Node | undefined; + flags: NodeBuilderFlags | undefined; + + // State encounteredError: boolean; - inObjectTypeLiteral: boolean; - checkAlias: boolean; symbolStack: Symbol[] | undefined; } @@ -2325,16 +2351,16 @@ namespace ts { enclosingDeclaration, flags, encounteredError: false, - inObjectTypeLiteral: false, - checkAlias: true, symbolStack: undefined }; } - function typeToTypeNodeHelper(type: Type): TypeNode { + function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode { + const inTypeAlias = context.flags & NodeBuilderFlags.InTypeAlias; + context.flags &= ~NodeBuilderFlags.InTypeAlias; + if (!type) { context.encounteredError = true; - // TODO(aozgaa): should we return implict any (undefined) or explicit any (keywordtypenode)? return undefined; } @@ -2350,23 +2376,25 @@ namespace ts { if (type.flags & TypeFlags.Boolean) { return createKeywordTypeNode(SyntaxKind.BooleanKeyword); } - if (type.flags & TypeFlags.Enum) { - const name = symbolToName(type.symbol, /*expectsIdentifier*/ false); + if (type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union)) { + const parentSymbol = getParentOfSymbol(type.symbol); + const parentName = symbolToName(parentSymbol, context, SymbolFlags.Type, /*expectsIdentifier*/ false); + const enumLiteralName = getDeclaredTypeOfSymbol(parentSymbol) === type ? parentName : createQualifiedName(parentName, getNameOfSymbol(type.symbol, context)); + return createTypeReferenceNode(enumLiteralName, /*typeArguments*/ undefined); + } + if (type.flags & TypeFlags.EnumLike) { + const name = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ false); return createTypeReferenceNode(name, /*typeArguments*/ undefined); } if (type.flags & (TypeFlags.StringLiteral)) { - return createLiteralTypeNode((createLiteral((type).text))); + return createLiteralTypeNode(setEmitFlags(createLiteral((type).value), EmitFlags.NoAsciiEscaping)); } if (type.flags & (TypeFlags.NumberLiteral)) { - return createLiteralTypeNode((createNumericLiteral((type).text))); + return createLiteralTypeNode((createLiteral((type).value))); } if (type.flags & TypeFlags.BooleanLiteral) { return (type).intrinsicName === "true" ? createTrue() : createFalse(); } - if (type.flags & TypeFlags.EnumLiteral) { - const name = symbolToName(type.symbol, /*expectsIdentifier*/ false); - return createTypeReferenceNode(name, /*typeArguments*/ undefined); - } if (type.flags & TypeFlags.Void) { return createKeywordTypeNode(SyntaxKind.VoidKeyword); } @@ -2386,8 +2414,8 @@ namespace ts { return createKeywordTypeNode(SyntaxKind.ObjectKeyword); } if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) { - if (context.inObjectTypeLiteral) { - if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowThisInObjectLiteral)) { + if (context.flags & NodeBuilderFlags.InObjectTypeLiteral) { + if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowThisInObjectLiteral)) { context.encounteredError = true; } } @@ -2400,84 +2428,58 @@ namespace ts { Debug.assert(!!(type.flags & TypeFlags.Object)); return typeReferenceToTypeNode(type); } - if (objectFlags & ObjectFlags.ClassOrInterface) { - Debug.assert(!!(type.flags & TypeFlags.Object)); - const name = symbolToName(type.symbol, /*expectsIdentifier*/ false); - // TODO(aozgaa): handle type arguments. - return createTypeReferenceNode(name, /*typeArguments*/ undefined); - } - if (type.flags & TypeFlags.TypeParameter) { - const name = symbolToName(type.symbol, /*expectsIdentifier*/ false); + if (type.flags & TypeFlags.TypeParameter || objectFlags & ObjectFlags.ClassOrInterface) { + const name = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ false); // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. return createTypeReferenceNode(name, /*typeArguments*/ undefined); } - - if (context.checkAlias && type.aliasSymbol) { - const name = symbolToName(type.aliasSymbol, /*expectsIdentifier*/ false); - const typeArgumentNodes = type.aliasTypeArguments && mapToTypeNodeArray(type.aliasTypeArguments); + if (!inTypeAlias && type.aliasSymbol && + isSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) { + const name = symbolToTypeReferenceName(type.aliasSymbol); + const typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context); return createTypeReferenceNode(name, typeArgumentNodes); } - context.checkAlias = false; - - if (type.flags & TypeFlags.Union) { - const formattedUnionTypes = formatUnionTypes((type).types); - const unionTypeNodes = formattedUnionTypes && mapToTypeNodeArray(formattedUnionTypes); - if (unionTypeNodes && unionTypeNodes.length > 0) { - return createUnionTypeNode(unionTypeNodes); + if (type.flags & (TypeFlags.Union | TypeFlags.Intersection)) { + const types = type.flags & TypeFlags.Union ? formatUnionTypes((type).types) : (type).types; + const typeNodes = mapToTypeNodes(types, context); + if (typeNodes && typeNodes.length > 0) { + const unionOrIntersectionTypeNode = createUnionOrIntersectionTypeNode(type.flags & TypeFlags.Union ? SyntaxKind.UnionType : SyntaxKind.IntersectionType, typeNodes); + return unionOrIntersectionTypeNode; } else { - if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowEmptyUnionOrIntersection)) { + if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { context.encounteredError = true; } return undefined; } } - - if (type.flags & TypeFlags.Intersection) { - return createIntersectionTypeNode(mapToTypeNodeArray((type as IntersectionType).types)); - } - if (objectFlags & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) { Debug.assert(!!(type.flags & TypeFlags.Object)); // The type is an object literal type. return createAnonymousTypeNode(type); } - if (type.flags & TypeFlags.Index) { const indexedType = (type).type; - const indexTypeNode = typeToTypeNodeHelper(indexedType); + const indexTypeNode = typeToTypeNodeHelper(indexedType, context); return createTypeOperatorNode(indexTypeNode); } if (type.flags & TypeFlags.IndexedAccess) { - const objectTypeNode = typeToTypeNodeHelper((type).objectType); - const indexTypeNode = typeToTypeNodeHelper((type).indexType); + const objectTypeNode = typeToTypeNodeHelper((type).objectType, context); + const indexTypeNode = typeToTypeNodeHelper((type).indexType, context); return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); } Debug.fail("Should be unreachable."); - function mapToTypeNodeArray(types: Type[]): TypeNode[] { - const result = []; - for (const type of types) { - const typeNode = typeToTypeNodeHelper(type); - if (typeNode) { - result.push(typeNode); - } - } - return result; - } - function createMappedTypeNodeFromType(type: MappedType) { Debug.assert(!!(type.flags & TypeFlags.Object)); - const typeParameter = getTypeParameterFromMappedType(type); - const typeParameterNode = typeParameterToDeclaration(typeParameter); - - const templateType = getTemplateTypeFromMappedType(type); - const templateTypeNode = typeToTypeNodeHelper(templateType); const readonlyToken = type.declaration && type.declaration.readonlyToken ? createToken(SyntaxKind.ReadonlyKeyword) : undefined; const questionToken = type.declaration && type.declaration.questionToken ? createToken(SyntaxKind.QuestionToken) : undefined; + const typeParameterNode = typeParameterToDeclaration(getTypeParameterFromMappedType(type), context); + const templateTypeNode = typeToTypeNodeHelper(getTemplateTypeFromMappedType(type), context); - return createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode); + const mappedTypeNode = createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode); + return setEmitFlags(mappedTypeNode, EmitFlags.SingleLine); } function createAnonymousTypeNode(type: ObjectType): TypeNode { @@ -2487,14 +2489,14 @@ namespace ts { if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) || symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) || shouldWriteTypeOfFunctionSymbol()) { - return createTypeQueryNodeFromSymbol(symbol); + return createTypeQueryNodeFromSymbol(symbol, SymbolFlags.Value); } else if (contains(context.symbolStack, symbol)) { // If type is an anonymous type literal in a type alias declaration, use type alias name const typeAlias = getTypeAliasForTypeLiteral(type); if (typeAlias) { // The specified symbol flags need to be reinterpreted as type flags - const entityName = symbolToName(typeAlias, /*expectsIdentifier*/ false); + const entityName = symbolToName(typeAlias, context, SymbolFlags.Type, /*expectsIdentifier*/ false); return createTypeReferenceNode(entityName, /*typeArguments*/ undefined); } else { @@ -2542,45 +2544,61 @@ namespace ts { const resolved = resolveStructuredTypeMembers(type); if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) { if (!resolved.callSignatures.length && !resolved.constructSignatures.length) { - return createTypeLiteralNode(/*members*/ undefined); + return setEmitFlags(createTypeLiteralNode(/*members*/ undefined), EmitFlags.SingleLine); } if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) { const signature = resolved.callSignatures[0]; - return signatureToSignatureDeclarationHelper(signature, SyntaxKind.FunctionType); + const signatureNode = signatureToSignatureDeclarationHelper(signature, SyntaxKind.FunctionType, context); + return signatureNode; + } + if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) { const signature = resolved.constructSignatures[0]; - return signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructorType); + const signatureNode = signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructorType, context); + return signatureNode; } } - const saveInObjectTypeLiteral = context.inObjectTypeLiteral; - context.inObjectTypeLiteral = true; + const savedFlags = context.flags; + context.flags |= NodeBuilderFlags.InObjectTypeLiteral; const members = createTypeNodesFromResolvedType(resolved); - context.inObjectTypeLiteral = saveInObjectTypeLiteral; - return createTypeLiteralNode(members); + context.flags = savedFlags; + const typeLiteralNode = createTypeLiteralNode(members); + return setEmitFlags(typeLiteralNode, EmitFlags.SingleLine); } - function createTypeQueryNodeFromSymbol(symbol: Symbol) { - const entityName = symbolToName(symbol, /*expectsIdentifier*/ false); + function createTypeQueryNodeFromSymbol(symbol: Symbol, symbolFlags: SymbolFlags) { + const entityName = symbolToName(symbol, context, symbolFlags, /*expectsIdentifier*/ false); return createTypeQueryNode(entityName); } + function symbolToTypeReferenceName(symbol: Symbol) { + // Unnamed function expressions and arrow functions have reserved names that we don't want to display + const entityName = symbol.flags & SymbolFlags.Class || !isReservedMemberName(symbol.name) ? symbolToName(symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ false) : createIdentifier(""); + return entityName; + } + function typeReferenceToTypeNode(type: TypeReference) { const typeArguments: Type[] = type.typeArguments || emptyArray; if (type.target === globalArrayType) { - const elementType = typeToTypeNodeHelper(typeArguments[0]); + if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) { + const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context); + return createTypeReferenceNode("Array", [typeArgumentNode]); + } + + const elementType = typeToTypeNodeHelper(typeArguments[0], context); return createArrayTypeNode(elementType); } else if (type.target.objectFlags & ObjectFlags.Tuple) { if (typeArguments.length > 0) { - const tupleConstituentNodes = mapToTypeNodeArray(typeArguments.slice(0, getTypeReferenceArity(type))); + const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, getTypeReferenceArity(type)), context); if (tupleConstituentNodes && tupleConstituentNodes.length > 0) { return createTupleTypeNode(tupleConstituentNodes); } } - if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowEmptyTuple)) { + if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowEmptyTuple)) { context.encounteredError = true; } return undefined; @@ -2588,7 +2606,7 @@ namespace ts { else { const outerTypeParameters = type.target.outerTypeParameters; let i = 0; - let qualifiedName: QualifiedName | undefined = undefined; + let qualifiedName: QualifiedName | undefined; if (outerTypeParameters) { const length = outerTypeParameters.length; while (i < length) { @@ -2601,47 +2619,80 @@ namespace ts { // When type parameters are their own type arguments for the whole group (i.e. we have // the default outer type arguments), we don't show the group. if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) { - const qualifiedNamePart = symbolToName(parent, /*expectsIdentifier*/ true); - if (!qualifiedName) { - qualifiedName = createQualifiedName(qualifiedNamePart, /*right*/ undefined); + const typeArgumentSlice = mapToTypeNodes(typeArguments.slice(start, i), context); + const typeArgumentNodes = typeArgumentSlice && createNodeArray(typeArgumentSlice); + const namePart = symbolToTypeReferenceName(parent); + (namePart.kind === SyntaxKind.Identifier ? namePart : namePart.right).typeArguments = typeArgumentNodes; + + if (qualifiedName) { + Debug.assert(!qualifiedName.right); + qualifiedName = addToQualifiedNameMissingRightIdentifier(qualifiedName, namePart); + qualifiedName = createQualifiedName(qualifiedName, /*right*/ undefined); } else { - Debug.assert(!qualifiedName.right); - qualifiedName.right = qualifiedNamePart; - qualifiedName = createQualifiedName(qualifiedName, /*right*/ undefined); + qualifiedName = createQualifiedName(namePart, /*right*/ undefined); } } } } + let entityName: EntityName = undefined; - const nameIdentifier = symbolToName(type.symbol, /*expectsIdentifier*/ true); + const nameIdentifier = symbolToTypeReferenceName(type.symbol); if (qualifiedName) { Debug.assert(!qualifiedName.right); - qualifiedName.right = nameIdentifier; + qualifiedName = addToQualifiedNameMissingRightIdentifier(qualifiedName, nameIdentifier); entityName = qualifiedName; } else { entityName = nameIdentifier; } - const typeParameterCount = (type.target.typeParameters || emptyArray).length; - const typeArgumentNodes = some(typeArguments) ? mapToTypeNodeArray(typeArguments.slice(i, typeParameterCount - i)) : undefined; + + let typeArgumentNodes: TypeNode[] | undefined; + if (typeArguments.length > 0) { + const typeParameterCount = (type.target.typeParameters || emptyArray).length; + typeArgumentNodes = mapToTypeNodes(typeArguments.slice(i, typeParameterCount), context); + } + + if (typeArgumentNodes) { + const lastIdentifier = entityName.kind === SyntaxKind.Identifier ? entityName : entityName.right; + lastIdentifier.typeArguments = undefined; + } + return createTypeReferenceNode(entityName, typeArgumentNodes); } } + function addToQualifiedNameMissingRightIdentifier(left: QualifiedName, right: Identifier | QualifiedName) { + Debug.assert(left.right === undefined); + + if (right.kind === SyntaxKind.Identifier) { + left.right = right; + return left; + } + + let rightPart = right; + while (rightPart.left.kind !== SyntaxKind.Identifier) { + rightPart = rightPart.left; + } + + left.right = rightPart.left; + rightPart.left = left; + return right; + } + function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] { const typeElements: TypeElement[] = []; for (const signature of resolvedType.callSignatures) { - typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature)); + typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature, context)); } for (const signature of resolvedType.constructSignatures) { - typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructSignature)); + typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructSignature, context)); } if (resolvedType.stringIndexInfo) { - typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.stringIndexInfo, IndexKind.String)); + typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.stringIndexInfo, IndexKind.String, context)); } if (resolvedType.numberIndexInfo) { - typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.numberIndexInfo, IndexKind.Number)); + typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.numberIndexInfo, IndexKind.Number, context)); } const properties = resolvedType.properties; @@ -2651,39 +2702,55 @@ namespace ts { for (const propertySymbol of properties) { const propertyType = getTypeOfSymbol(propertySymbol); - const oldDeclaration = propertySymbol.declarations && propertySymbol.declarations[0] as TypeElement; - if (!oldDeclaration) { - return; - } - const propertyName = oldDeclaration.name; + const saveEnclosingDeclaration = context.enclosingDeclaration; + context.enclosingDeclaration = undefined; + const propertyName = symbolToName(propertySymbol, context, SymbolFlags.Value, /*expectsIdentifier*/ true); + context.enclosingDeclaration = saveEnclosingDeclaration; const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined; if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length) { const signatures = getSignaturesOfType(propertyType, SignatureKind.Call); for (const signature of signatures) { - const methodDeclaration = signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature); + const methodDeclaration = signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature, context); methodDeclaration.name = propertyName; methodDeclaration.questionToken = optionalToken; typeElements.push(methodDeclaration); } } else { + const propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : createKeywordTypeNode(SyntaxKind.AnyKeyword); - // TODO(aozgaa): should we create a node with explicit or implict any? - const propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType) : createKeywordTypeNode(SyntaxKind.AnyKeyword); - typeElements.push(createPropertySignature( + const modifiers = isReadonlySymbol(propertySymbol) ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined; + const propertySignature = createPropertySignature( + modifiers, propertyName, optionalToken, propertyTypeNode, - /*initializer*/ undefined)); + /*initializer*/ undefined); + typeElements.push(propertySignature); } } return typeElements.length ? typeElements : undefined; } } - function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, kind: IndexKind): IndexSignatureDeclaration { + function mapToTypeNodes(types: Type[], context: NodeBuilderContext): TypeNode[] { + if (some(types)) { + const result = []; + for (let i = 0; i < types.length; ++i) { + const type = types[i]; + const typeNode = typeToTypeNodeHelper(type, context); + if (typeNode) { + result.push(typeNode); + } + } + + return result; + } + } + + function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, kind: IndexKind, context: NodeBuilderContext): IndexSignatureDeclaration { + const name = getNameFromIndexInfo(indexInfo) || "x"; const indexerTypeNode = createKeywordTypeNode(kind === IndexKind.String ? SyntaxKind.StringKeyword : SyntaxKind.NumberKeyword); - const name = getNameFromIndexInfo(indexInfo); const indexingParameter = createParameter( /*decorators*/ undefined, @@ -2693,7 +2760,7 @@ namespace ts { /*questionToken*/ undefined, indexerTypeNode, /*initializer*/ undefined); - const typeNode = typeToTypeNodeHelper(indexInfo.type); + const typeNode = typeToTypeNodeHelper(indexInfo.type, context); return createIndexSignature( /*decorators*/ undefined, indexInfo.isReadonly ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined, @@ -2701,61 +2768,93 @@ namespace ts { typeNode); } - function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind): SignatureDeclaration { - - const typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter)); - const parameters = signature.parameters.map(parameter => symbolToParameterDeclaration(parameter)); - let returnTypeNode: TypeNode | TypePredicate; + function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind, context: NodeBuilderContext): SignatureDeclaration { + const typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, context)); + const parameters = signature.parameters.map(parameter => symbolToParameterDeclaration(parameter, context)); + if (signature.thisParameter) { + const thisParameter = symbolToParameterDeclaration(signature.thisParameter, context); + parameters.unshift(thisParameter); + } + let returnTypeNode: TypeNode; if (signature.typePredicate) { const typePredicate = signature.typePredicate; - const parameterName = typePredicate.kind === TypePredicateKind.Identifier ? createIdentifier((typePredicate).parameterName) : createThisTypeNode(); - const typeNode = typeToTypeNodeHelper(typePredicate.type); + const parameterName = typePredicate.kind === TypePredicateKind.Identifier ? + setEmitFlags(createIdentifier((typePredicate).parameterName), EmitFlags.NoAsciiEscaping) : + createThisTypeNode(); + const typeNode = typeToTypeNodeHelper(typePredicate.type, context); returnTypeNode = createTypePredicateNode(parameterName, typeNode); } else { const returnType = getReturnTypeOfSignature(signature); - returnTypeNode = returnType && typeToTypeNodeHelper(returnType); + returnTypeNode = returnType && typeToTypeNodeHelper(returnType, context); } - const returnTypeNodeExceptAny = returnTypeNode && returnTypeNode.kind !== SyntaxKind.AnyKeyword ? returnTypeNode : undefined; - - return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNodeExceptAny); + if (context.flags & NodeBuilderFlags.SuppressAnyReturnType) { + if (returnTypeNode && returnTypeNode.kind === SyntaxKind.AnyKeyword) { + returnTypeNode = undefined; + } + } + else if (!returnTypeNode) { + returnTypeNode = createKeywordTypeNode(SyntaxKind.AnyKeyword); + } + return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode); } - function typeParameterToDeclaration(type: TypeParameter): TypeParameterDeclaration { + function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext): TypeParameterDeclaration { + const name = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true); const constraint = getConstraintFromTypeParameter(type); - const constraintNode = constraint && typeToTypeNodeHelper(constraint); + const constraintNode = constraint && typeToTypeNodeHelper(constraint, context); const defaultParameter = getDefaultFromTypeParameter(type); - const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter); - const name = symbolToName(type.symbol, /*expectsIdentifier*/ true); + const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context); return createTypeParameterDeclaration(name, constraintNode, defaultParameterNode); } - function symbolToParameterDeclaration(parameterSymbol: Symbol): ParameterDeclaration { - const parameterDeclaration = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); - const parameterType = getTypeOfSymbol(parameterSymbol); - const parameterTypeNode = typeToTypeNodeHelper(parameterType); - // TODO(aozgaa): In the future, check initializer accessibility. + function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext): ParameterDeclaration { + const parameterDeclaration = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); + const modifiers = parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone); + const dotDotDotToken = isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined; + const name = parameterDeclaration.name.kind === SyntaxKind.Identifier ? + setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) : + cloneBindingName(parameterDeclaration.name); + const questionToken = isOptionalParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : undefined; + + let parameterType = getTypeOfSymbol(parameterSymbol); + if (isRequiredInitializedParameter(parameterDeclaration)) { + parameterType = getNullableType(parameterType, TypeFlags.Undefined); + } + const parameterTypeNode = typeToTypeNodeHelper(parameterType, context); + const parameterNode = createParameter( - parameterDeclaration.decorators, - parameterDeclaration.modifiers, - parameterDeclaration.dotDotDotToken && createToken(SyntaxKind.DotDotDotToken), - // Clone name to remove trivia. - getSynthesizedClone(parameterDeclaration.name), - parameterDeclaration.questionToken && createToken(SyntaxKind.QuestionToken), + /*decorators*/ undefined, + modifiers, + dotDotDotToken, + name, + questionToken, parameterTypeNode, - parameterDeclaration.initializer); + /*initializer*/ undefined); return parameterNode; + + function cloneBindingName(node: BindingName): BindingName { + return elideInitializerAndSetEmitFlags(node); + function elideInitializerAndSetEmitFlags(node: Node): Node { + const visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags); + const clone = nodeIsSynthesized(visited) ? visited : getSynthesizedClone(visited); + if (clone.kind === SyntaxKind.BindingElement) { + (clone).initializer = undefined; + } + return setEmitFlags(clone, EmitFlags.SingleLine | EmitFlags.NoAsciiEscaping); + } + } } - function symbolToName(symbol: Symbol, expectsIdentifier: true): Identifier; - function symbolToName(symbol: Symbol, expectsIdentifier: false): EntityName; - function symbolToName(symbol: Symbol, expectsIdentifier: boolean): EntityName { + function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: true): Identifier; + function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: false): EntityName; + function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: boolean): EntityName { // Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration. let chain: Symbol[]; const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter; - if (!isTypeParameter && context.enclosingDeclaration) { - chain = getSymbolChain(symbol, SymbolFlags.None, /*endOfChain*/ true); + if (!isTypeParameter && (context.enclosingDeclaration || context.flags & NodeBuilderFlags.UseFullyQualifiedType)) { + chain = getSymbolChain(symbol, meaning, /*endOfChain*/ true); Debug.assert(chain && chain.length > 0); } else { @@ -2764,18 +2863,16 @@ namespace ts { if (expectsIdentifier && chain.length !== 1 && !context.encounteredError - && !(context.flags & NodeBuilderFlags.allowQualifedNameInPlaceOfIdentifier)) { + && !(context.flags & NodeBuilderFlags.AllowQualifedNameInPlaceOfIdentifier)) { context.encounteredError = true; } return createEntityNameFromSymbolChain(chain, chain.length - 1); function createEntityNameFromSymbolChain(chain: Symbol[], index: number): EntityName { Debug.assert(chain && 0 <= index && index < chain.length); - // const parentIndex = index - 1; const symbol = chain[index]; - let typeParameterString = ""; - if (index > 0) { - + let typeParameterNodes: TypeNode[] | undefined; + if (context.flags & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index > 0) { const parentSymbol = chain[index - 1]; let typeParameters: TypeParameter[]; if (getCheckFlags(symbol) & CheckFlags.Instantiated) { @@ -2787,21 +2884,12 @@ namespace ts { typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); } } - if (typeParameters && typeParameters.length > 0) { - if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowTypeParameterInQualifiedName)) { - context.encounteredError = true; - } - const writer = getSingleLineStringWriter(); - const displayBuilder = getSymbolDisplayBuilder(); - displayBuilder.buildDisplayForTypeParametersAndDelimiters(typeParameters, writer, context.enclosingDeclaration, 0); - typeParameterString = writer.string(); - releaseStringWriter(writer); - } + typeParameterNodes = mapToTypeNodes(typeParameters, context); } - const symbolName = getNameOfSymbol(symbol); - const symbolNameWithTypeParameters = typeParameterString.length > 0 ? `${symbolName}<${typeParameterString}>` : symbolName; - const identifier = createIdentifier(symbolNameWithTypeParameters); + + const symbolName = getNameOfSymbol(symbol, context); + const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); return index > 0 ? createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; } @@ -2839,30 +2927,30 @@ namespace ts { return [symbol]; } } + } - function getNameOfSymbol(symbol: Symbol): string { - const declaration = firstOrUndefined(symbol.declarations); - if (declaration) { - const name = getNameOfDeclaration(declaration); - if (name) { - return declarationNameToString(name); - } - if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) { - return declarationNameToString((declaration.parent).name); - } - if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowAnonymousIdentifier)) { - context.encounteredError = true; - } - switch (declaration.kind) { - case SyntaxKind.ClassExpression: - return "(Anonymous class)"; - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - return "(Anonymous function)"; - } + function getNameOfSymbol(symbol: Symbol, context: NodeBuilderContext): string { + const declaration = firstOrUndefined(symbol.declarations); + if (declaration) { + const name = getNameOfDeclaration(declaration); + if (name) { + return declarationNameToString(name); + } + if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) { + return declarationNameToString((declaration.parent).name); + } + if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) { + context.encounteredError = true; + } + switch (declaration.kind) { + case SyntaxKind.ClassExpression: + return "(Anonymous class)"; + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + return "(Anonymous function)"; } - return symbol.name; } + return symbol.name; } } @@ -2883,12 +2971,14 @@ namespace ts { flags |= t.flags; if (!(t.flags & TypeFlags.Nullable)) { if (t.flags & (TypeFlags.BooleanLiteral | TypeFlags.EnumLiteral)) { - const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : (t).baseType; - const count = baseType.types.length; - if (i + count <= types.length && types[i + count - 1] === baseType.types[count - 1]) { - result.push(baseType); - i += count - 1; - continue; + const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLiteralType(t); + if (baseType.flags & TypeFlags.Union) { + const count = (baseType).types.length; + if (i + count <= types.length && types[i + count - 1] === (baseType).types[count - 1]) { + result.push(baseType); + i += count - 1; + continue; + } } } result.push(t); @@ -2926,7 +3016,7 @@ namespace ts { } function literalTypeToString(type: LiteralType) { - return type.flags & TypeFlags.StringLiteral ? `"${escapeString((type).text)}"` : (type).text; + return type.flags & TypeFlags.StringLiteral ? `"${escapeString((type).value)}"` : "" + (type).value; } function getNameOfSymbol(symbol: Symbol): string { @@ -3087,12 +3177,17 @@ namespace ts { else if (getObjectFlags(type) & ObjectFlags.Reference) { writeTypeReference(type, nextFlags); } - else if (type.flags & TypeFlags.EnumLiteral) { - buildSymbolDisplay(getParentOfSymbol(type.symbol), writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags); - writePunctuation(writer, SyntaxKind.DotToken); - appendSymbolNameOnly(type.symbol, writer); + else if (type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union)) { + const parent = getParentOfSymbol(type.symbol); + buildSymbolDisplay(parent, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags); + // In a literal enum type with a single member E { A }, E and E.A denote the + // same type. We always display this type simply as E. + if (getDeclaredTypeOfSymbol(parent) !== type) { + writePunctuation(writer, SyntaxKind.DotToken); + appendSymbolNameOnly(type.symbol, writer); + } } - else if (getObjectFlags(type) & ObjectFlags.ClassOrInterface || type.flags & (TypeFlags.Enum | TypeFlags.TypeParameter)) { + else if (getObjectFlags(type) & ObjectFlags.ClassOrInterface || type.flags & (TypeFlags.EnumLike | TypeFlags.TypeParameter)) { // The specified symbol flags need to be reinterpreted as type flags buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags); } @@ -3463,7 +3558,7 @@ namespace ts { let type = getTypeOfSymbol(p); if (parameterNode && isRequiredInitializedParameter(parameterNode)) { - type = includeFalsyTypes(type, TypeFlags.Undefined); + type = getNullableType(type, TypeFlags.Undefined); } buildTypeDisplay(type, writer, enclosingDeclaration, flags, symbolStack); } @@ -4039,7 +4134,7 @@ namespace ts { } function addOptionality(type: Type, optional: boolean): Type { - return strictNullChecks && optional ? includeFalsyTypes(type, TypeFlags.Undefined) : type; + return strictNullChecks && optional ? getNullableType(type, TypeFlags.Undefined) : type; } // Return the inferred type for a variable, parameter, or property declaration @@ -4100,7 +4195,7 @@ namespace ts { const func = declaration.parent; // For a parameter of a set accessor, use the type of the get accessor if one is present if (func.kind === SyntaxKind.SetAccessor && !hasDynamicName(func)) { - const getter = getDeclarationOfKind(declaration.parent.symbol, SyntaxKind.GetAccessor); + const getter = getDeclarationOfKind(declaration.parent.symbol, SyntaxKind.GetAccessor); if (getter) { const getterSignature = getSignatureFromDeclaration(getter); const thisParameter = getAccessorThisParameter(func as AccessorDeclaration); @@ -4389,8 +4484,8 @@ namespace ts { function getTypeOfAccessors(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { - const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); - const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); + const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); + const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); if (getter && getter.flags & NodeFlags.JavaScriptFile) { const jsDocType = getTypeForDeclarationFromJSDocComment(getter); @@ -4439,7 +4534,7 @@ namespace ts { if (!popTypeResolution()) { type = anyType; if (noImplicitAny) { - const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); + const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); } } @@ -4466,7 +4561,7 @@ namespace ts { links.type = baseTypeVariable ? getIntersectionType([type, baseTypeVariable]) : type; } else { - links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ? includeFalsyTypes(type, TypeFlags.Undefined) : type; + links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ? getNullableType(type, TypeFlags.Undefined) : type; } } } @@ -4916,7 +5011,7 @@ namespace ts { return unknownType; } - let declaration: JSDocTypedefTag | TypeAliasDeclaration = getDeclarationOfKind(symbol, SyntaxKind.JSDocTypedefTag); + let declaration: JSDocTypedefTag | TypeAliasDeclaration = getDeclarationOfKind(symbol, SyntaxKind.JSDocTypedefTag); let type: Type; if (declaration) { if (declaration.jsDocTypeLiteral) { @@ -4927,7 +5022,7 @@ namespace ts { } } else { - declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration); + declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration); type = getTypeFromTypeNode(declaration.type); } @@ -4950,77 +5045,80 @@ namespace ts { return links.declaredType; } - function isLiteralEnumMember(symbol: Symbol, member: EnumMember) { + function isLiteralEnumMember(member: EnumMember) { const expr = member.initializer; if (!expr) { return !isInAmbientContext(member); } - return expr.kind === SyntaxKind.NumericLiteral || + return expr.kind === SyntaxKind.StringLiteral || expr.kind === SyntaxKind.NumericLiteral || expr.kind === SyntaxKind.PrefixUnaryExpression && (expr).operator === SyntaxKind.MinusToken && (expr).operand.kind === SyntaxKind.NumericLiteral || - expr.kind === SyntaxKind.Identifier && !!symbol.exports.get((expr).text); + expr.kind === SyntaxKind.Identifier && (nodeIsMissing(expr) || !!getSymbolOfNode(member.parent).exports.get((expr).text)); } - function enumHasLiteralMembers(symbol: Symbol) { + function getEnumKind(symbol: Symbol): EnumKind { + const links = getSymbolLinks(symbol); + if (links.enumKind !== undefined) { + return links.enumKind; + } + let hasNonLiteralMember = false; for (const declaration of symbol.declarations) { if (declaration.kind === SyntaxKind.EnumDeclaration) { for (const member of (declaration).members) { - if (!isLiteralEnumMember(symbol, member)) { - return false; + if (member.initializer && member.initializer.kind === SyntaxKind.StringLiteral) { + return links.enumKind = EnumKind.Literal; + } + if (!isLiteralEnumMember(member)) { + hasNonLiteralMember = true; } } } } - return true; + return links.enumKind = hasNonLiteralMember ? EnumKind.Numeric : EnumKind.Literal; } - function createEnumLiteralType(symbol: Symbol, baseType: EnumType, text: string) { - const type = createType(TypeFlags.EnumLiteral); - type.symbol = symbol; - type.baseType = baseType; - type.text = text; - return type; + function getBaseTypeOfEnumLiteralType(type: Type) { + return type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)) : type; } function getDeclaredTypeOfEnum(symbol: Symbol): Type { const links = getSymbolLinks(symbol); - if (!links.declaredType) { - const enumType = links.declaredType = createType(TypeFlags.Enum); - enumType.symbol = symbol; - if (enumHasLiteralMembers(symbol)) { - const memberTypeList: Type[] = []; - const memberTypes: EnumLiteralType[] = []; - for (const declaration of enumType.symbol.declarations) { - if (declaration.kind === SyntaxKind.EnumDeclaration) { - computeEnumMemberValues(declaration); - for (const member of (declaration).members) { - const memberSymbol = getSymbolOfNode(member); - const value = getEnumMemberValue(member); - if (!memberTypes[value]) { - const memberType = memberTypes[value] = createEnumLiteralType(memberSymbol, enumType, "" + value); - memberTypeList.push(memberType); - } - } + if (links.declaredType) { + return links.declaredType; + } + if (getEnumKind(symbol) === EnumKind.Literal) { + enumCount++; + const memberTypeList: Type[] = []; + for (const declaration of symbol.declarations) { + if (declaration.kind === SyntaxKind.EnumDeclaration) { + for (const member of (declaration).members) { + const memberType = getLiteralType(getEnumMemberValue(member), enumCount, getSymbolOfNode(member)); + getSymbolLinks(getSymbolOfNode(member)).declaredType = memberType; + memberTypeList.push(memberType); } } - enumType.memberTypes = memberTypes; - if (memberTypeList.length > 1) { - enumType.flags |= TypeFlags.Union; - (enumType).types = memberTypeList; - unionTypes.set(getTypeListId(memberTypeList), enumType); + } + if (memberTypeList.length) { + const enumType = getUnionType(memberTypeList, /*subtypeReduction*/ false, symbol, /*aliasTypeArguments*/ undefined); + if (enumType.flags & TypeFlags.Union) { + enumType.flags |= TypeFlags.EnumLiteral; + enumType.symbol = symbol; } + return links.declaredType = enumType; } } - return links.declaredType; + const enumType = createType(TypeFlags.Enum); + enumType.symbol = symbol; + return links.declaredType = enumType; } function getDeclaredTypeOfEnumMember(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.declaredType) { - const enumType = getDeclaredTypeOfEnum(getParentOfSymbol(symbol)); - links.declaredType = enumType.flags & TypeFlags.Union ? - enumType.memberTypes[getEnumMemberValue(symbol.valueDeclaration)] : - enumType; + const enumType = getDeclaredTypeOfEnum(getParentOfSymbol(symbol)); + if (!links.declaredType) { + links.declaredType = enumType; + } } return links.declaredType; } @@ -5551,7 +5649,7 @@ namespace ts { // If the current iteration type constituent is a string literal type, create a property. // Otherwise, for type string create a string index signature. if (t.flags & TypeFlags.StringLiteral) { - const propName = (t).text; + const propName = (t).value; const modifiersProp = getPropertyOfType(modifiersType, propName); const isOptional = templateOptional || !!(modifiersProp && modifiersProp.flags & SymbolFlags.Optional); const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName); @@ -5696,6 +5794,10 @@ namespace ts { if (type.flags & TypeFlags.Union) { const props = createMap(); for (const memberType of (type as UnionType).types) { + if (memberType.flags & TypeFlags.Primitive) { + continue; + } + for (const { name } of getPropertiesOfType(memberType)) { if (!props.has(name)) { props.set(name, createUnionOrIntersectionProperty(type as UnionType, name)); @@ -6220,7 +6322,7 @@ namespace ts { !hasDynamicName(declaration) && (!hasThisParameter || !thisParameter)) { const otherKind = declaration.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const other = getDeclarationOfKind(declaration.symbol, otherKind); + const other = getDeclarationOfKind(declaration.symbol, otherKind); if (other) { thisParameter = getAnnotatedAccessorThisParameter(other); } @@ -6263,7 +6365,7 @@ namespace ts { // TypeScript 1.0 spec (April 2014): // If only one accessor includes a type annotation, the other behaves as if it had the same type annotation. if (declaration.kind === SyntaxKind.GetAccessor && !hasDynamicName(declaration)) { - const setter = getDeclarationOfKind(declaration.symbol, SyntaxKind.SetAccessor); + const setter = getDeclarationOfKind(declaration.symbol, SyntaxKind.SetAccessor); return getAnnotatedAccessorType(setter); } @@ -6476,7 +6578,7 @@ namespace ts { } function getConstraintDeclaration(type: TypeParameter) { - return (getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter)).constraint; + return getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter).constraint; } function getConstraintFromTypeParameter(typeParameter: TypeParameter): Type { @@ -7276,7 +7378,7 @@ namespace ts { function getLiteralTypeFromPropertyName(prop: Symbol) { return getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier || startsWith(prop.name, "__@") ? neverType : - getLiteralTypeForText(TypeFlags.StringLiteral, unescapeIdentifier(prop.name)); + getLiteralType(unescapeIdentifier(prop.name)); } function getLiteralTypeFromPropertyNames(type: Type) { @@ -7312,8 +7414,8 @@ namespace ts { 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.StringLiteral | TypeFlags.NumberLiteral | TypeFlags.EnumLiteral) ? - (indexType).text : + const propName = indexType.flags & TypeFlags.StringOrNumberLiteral ? + "" + (indexType).value : accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? getPropertyNameForKnownSymbolName(((accessExpression.argumentExpression).name).text) : undefined; @@ -7361,7 +7463,7 @@ namespace ts { if (accessNode) { const indexNode = accessNode.kind === SyntaxKind.ElementAccessExpression ? (accessNode).argumentExpression : (accessNode).indexType; if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { - error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType).text, typeToString(objectType)); + error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, "" + (indexType).value, typeToString(objectType)); } else if (indexType.flags & (TypeFlags.String | TypeFlags.Number)) { error(indexNode, Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType)); @@ -7572,16 +7674,17 @@ namespace ts { return prop.flags & SymbolFlags.Method && find(prop.declarations, decl => isClassLike(decl.parent)); } - function createLiteralType(flags: TypeFlags, text: string) { + function createLiteralType(flags: TypeFlags, value: string | number, symbol: Symbol) { const type = createType(flags); - type.text = text; + type.symbol = symbol; + type.value = value; return type; } function getFreshTypeOfLiteralType(type: Type) { if (type.flags & TypeFlags.StringOrNumberLiteral && !(type.flags & TypeFlags.FreshLiteral)) { if (!(type).freshType) { - const freshType = createLiteralType(type.flags | TypeFlags.FreshLiteral, (type).text); + const freshType = createLiteralType(type.flags | TypeFlags.FreshLiteral, (type).value, (type).symbol); freshType.regularType = type; (type).freshType = freshType; } @@ -7594,11 +7697,17 @@ namespace ts { return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (type).regularType : type; } - function getLiteralTypeForText(flags: TypeFlags, text: string) { - const map = flags & TypeFlags.StringLiteral ? stringLiteralTypes : numericLiteralTypes; - let type = map.get(text); + function getLiteralType(value: string | number, enumId?: number, symbol?: Symbol) { + // We store all literal types in a single map with keys of the form '#NNN' and '@SSS', + // where NNN is the text representation of a numeric literal and SSS are the characters + // of a string literal. For literal enum members we use 'EEE#NNN' and 'EEE@SSS', where + // EEE is a unique id for the containing enum type. + const qualifier = typeof value === "number" ? "#" : "@"; + const key = enumId ? enumId + qualifier + value : qualifier + value; + let type = literalTypes.get(key); if (!type) { - map.set(text, type = createLiteralType(flags, text)); + const flags = (typeof value === "number" ? TypeFlags.NumberLiteral : TypeFlags.StringLiteral) | (enumId ? TypeFlags.EnumLiteral : 0); + literalTypes.set(key, type = createLiteralType(flags, value, symbol)); } return type; } @@ -8445,29 +8554,27 @@ namespace ts { false; } - function isEnumTypeRelatedTo(source: EnumType, target: EnumType, errorReporter?: ErrorReporter) { - if (source === target) { + function isEnumTypeRelatedTo(sourceSymbol: Symbol, targetSymbol: Symbol, errorReporter?: ErrorReporter) { + if (sourceSymbol === targetSymbol) { return true; } - const id = source.id + "," + target.id; + const id = getSymbolId(sourceSymbol) + "," + getSymbolId(targetSymbol); const relation = enumRelation.get(id); if (relation !== undefined) { return relation; } - if (source.symbol.name !== target.symbol.name || - !(source.symbol.flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum) || - (source.flags & TypeFlags.Union) !== (target.flags & TypeFlags.Union)) { + if (sourceSymbol.name !== targetSymbol.name || !(sourceSymbol.flags & SymbolFlags.RegularEnum) || !(targetSymbol.flags & SymbolFlags.RegularEnum)) { enumRelation.set(id, false); return false; } - const targetEnumType = getTypeOfSymbol(target.symbol); - for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) { + const targetEnumType = getTypeOfSymbol(targetSymbol); + for (const property of getPropertiesOfType(getTypeOfSymbol(sourceSymbol))) { if (property.flags & SymbolFlags.EnumMember) { const targetProperty = getPropertyOfType(targetEnumType, property.name); if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { if (errorReporter) { errorReporter(Diagnostics.Property_0_is_missing_in_type_1, property.name, - typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); + typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); } enumRelation.set(id, false); return false; @@ -8479,30 +8586,36 @@ namespace ts { } function isSimpleTypeRelatedTo(source: Type, target: Type, relation: Map, errorReporter?: ErrorReporter) { - if (target.flags & TypeFlags.Never) return false; - if (target.flags & TypeFlags.Any || source.flags & TypeFlags.Never) return true; - if (source.flags & TypeFlags.StringLike && target.flags & TypeFlags.String) return true; - if (source.flags & TypeFlags.NumberLike && target.flags & TypeFlags.Number) return true; - if (source.flags & TypeFlags.BooleanLike && target.flags & TypeFlags.Boolean) return true; - if (source.flags & TypeFlags.EnumLiteral && target.flags & TypeFlags.Enum && (source).baseType === target) return true; - if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum && isEnumTypeRelatedTo(source, target, errorReporter)) return true; - if (source.flags & TypeFlags.Undefined && (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void))) return true; - if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true; - if (source.flags & TypeFlags.Object && target.flags & TypeFlags.NonPrimitive) return true; + const s = source.flags; + const t = target.flags; + if (t & TypeFlags.Never) return false; + if (t & TypeFlags.Any || s & TypeFlags.Never) return true; + if (s & TypeFlags.StringLike && t & TypeFlags.String) return true; + if (s & TypeFlags.StringLiteral && s & TypeFlags.EnumLiteral && + t & TypeFlags.StringLiteral && !(t & TypeFlags.EnumLiteral) && + (source).value === (target).value) return true; + if (s & TypeFlags.NumberLike && t & TypeFlags.Number) return true; + if (s & TypeFlags.NumberLiteral && s & TypeFlags.EnumLiteral && + t & TypeFlags.NumberLiteral && !(t & TypeFlags.EnumLiteral) && + (source).value === (target).value) return true; + if (s & TypeFlags.BooleanLike && t & TypeFlags.Boolean) return true; + if (s & TypeFlags.Enum && t & TypeFlags.Enum && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; + if (s & TypeFlags.EnumLiteral && t & TypeFlags.EnumLiteral) { + if (s & TypeFlags.Union && t & TypeFlags.Union && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; + if (s & TypeFlags.Literal && t & TypeFlags.Literal && + (source).value === (target).value && + isEnumTypeRelatedTo(getParentOfSymbol(source.symbol), getParentOfSymbol(target.symbol), errorReporter)) return true; + } + if (s & TypeFlags.Undefined && (!strictNullChecks || t & (TypeFlags.Undefined | TypeFlags.Void))) return true; + if (s & TypeFlags.Null && (!strictNullChecks || t & TypeFlags.Null)) return true; + if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive) return true; if (relation === assignableRelation || relation === comparableRelation) { - if (source.flags & TypeFlags.Any) return true; - if ((source.flags & TypeFlags.Number | source.flags & TypeFlags.NumberLiteral) && target.flags & TypeFlags.EnumLike) return true; - if (source.flags & TypeFlags.EnumLiteral && - target.flags & TypeFlags.EnumLiteral && - (source).text === (target).text && - isEnumTypeRelatedTo((source).baseType, (target).baseType, errorReporter)) { - return true; - } - if (source.flags & TypeFlags.EnumLiteral && - target.flags & TypeFlags.Enum && - isEnumTypeRelatedTo(target, (source).baseType, errorReporter)) { - return true; - } + if (s & TypeFlags.Any) return true; + // Type number or any numeric literal type is assignable to any numeric enum type or any + // numeric enum literal type. This rule exists for backwards compatibility reasons because + // bit-flag enum types sometimes look like literal enum types with numeric literal values. + if (s & (TypeFlags.Number | TypeFlags.NumberLiteral) && !(s & TypeFlags.EnumLiteral) && ( + t & TypeFlags.Enum || t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true; } return false; } @@ -9656,7 +9769,7 @@ namespace ts { return getUnionType(types, /*subtypeReduction*/ true); } const supertype = getSupertypeOrUnion(primaryTypes); - return supertype && includeFalsyTypes(supertype, getFalsyFlagsOfTypes(types) & TypeFlags.Nullable); + return supertype && getNullableType(supertype, getFalsyFlagsOfTypes(types) & TypeFlags.Nullable); } function reportNoCommonSupertypeError(types: Type[], errorLocation: Node, errorMessageChainHead: DiagnosticMessageChain): void { @@ -9721,26 +9834,26 @@ namespace ts { function isLiteralType(type: Type): boolean { return type.flags & TypeFlags.Boolean ? true : - type.flags & TypeFlags.Union ? type.flags & TypeFlags.Enum ? true : !forEach((type).types, t => !isUnitType(t)) : - isUnitType(type); + type.flags & TypeFlags.Union ? type.flags & TypeFlags.EnumLiteral ? true : !forEach((type).types, t => !isUnitType(t)) : + isUnitType(type); } function getBaseTypeOfLiteralType(type: Type): Type { - return type.flags & TypeFlags.StringLiteral ? stringType : + return type.flags & TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(type) : + type.flags & TypeFlags.StringLiteral ? stringType : type.flags & TypeFlags.NumberLiteral ? numberType : - type.flags & TypeFlags.BooleanLiteral ? booleanType : - type.flags & TypeFlags.EnumLiteral ? (type).baseType : - type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(sameMap((type).types, getBaseTypeOfLiteralType)) : - type; + type.flags & TypeFlags.BooleanLiteral ? booleanType : + type.flags & TypeFlags.Union ? getUnionType(sameMap((type).types, getBaseTypeOfLiteralType)) : + type; } function getWidenedLiteralType(type: Type): Type { - return type.flags & TypeFlags.StringLiteral && type.flags & TypeFlags.FreshLiteral ? stringType : + return type.flags & TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(type) : + type.flags & TypeFlags.StringLiteral && type.flags & TypeFlags.FreshLiteral ? stringType : type.flags & TypeFlags.NumberLiteral && type.flags & TypeFlags.FreshLiteral ? numberType : - type.flags & TypeFlags.BooleanLiteral ? booleanType : - type.flags & TypeFlags.EnumLiteral ? (type).baseType : - type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(sameMap((type).types, getWidenedLiteralType)) : - type; + type.flags & TypeFlags.BooleanLiteral ? booleanType : + type.flags & TypeFlags.Union ? getUnionType(sameMap((type).types, getWidenedLiteralType)) : + type; } /** @@ -9764,24 +9877,10 @@ namespace ts { // no flags for all other types (including non-falsy literal types). function getFalsyFlags(type: Type): TypeFlags { return type.flags & TypeFlags.Union ? getFalsyFlagsOfTypes((type).types) : - type.flags & TypeFlags.StringLiteral ? (type).text === "" ? TypeFlags.StringLiteral : 0 : - type.flags & TypeFlags.NumberLiteral ? (type).text === "0" ? TypeFlags.NumberLiteral : 0 : - type.flags & TypeFlags.BooleanLiteral ? type === falseType ? TypeFlags.BooleanLiteral : 0 : - type.flags & TypeFlags.PossiblyFalsy; - } - - function includeFalsyTypes(type: Type, flags: TypeFlags) { - if ((getFalsyFlags(type) & flags) === flags) { - return type; - } - const types = [type]; - if (flags & TypeFlags.StringLike) types.push(emptyStringType); - if (flags & TypeFlags.NumberLike) types.push(zeroType); - if (flags & TypeFlags.BooleanLike) types.push(falseType); - if (flags & TypeFlags.Void) types.push(voidType); - if (flags & TypeFlags.Undefined) types.push(undefinedType); - if (flags & TypeFlags.Null) types.push(nullType); - return getUnionType(types); + type.flags & TypeFlags.StringLiteral ? (type).value === "" ? TypeFlags.StringLiteral : 0 : + type.flags & TypeFlags.NumberLiteral ? (type).value === 0 ? TypeFlags.NumberLiteral : 0 : + type.flags & TypeFlags.BooleanLiteral ? type === falseType ? TypeFlags.BooleanLiteral : 0 : + type.flags & TypeFlags.PossiblyFalsy; } function removeDefinitelyFalsyTypes(type: Type): Type { @@ -9790,6 +9889,28 @@ namespace ts { type; } + function extractDefinitelyFalsyTypes(type: Type): Type { + return mapType(type, getDefinitelyFalsyPartOfType); + } + + function getDefinitelyFalsyPartOfType(type: Type): Type { + return type.flags & TypeFlags.String ? emptyStringType : + type.flags & TypeFlags.Number ? zeroType : + type.flags & TypeFlags.Boolean || type === falseType ? falseType : + type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null) || + type.flags & TypeFlags.StringLiteral && (type).value === "" || + type.flags & TypeFlags.NumberLiteral && (type).value === 0 ? type : + neverType; + } + + function getNullableType(type: Type, flags: TypeFlags): Type { + const missing = (flags & ~type.flags) & (TypeFlags.Undefined | TypeFlags.Null); + return missing === 0 ? type : + missing === TypeFlags.Undefined ? getUnionType([type, undefinedType]) : + missing === TypeFlags.Null ? getUnionType([type, nullType]) : + getUnionType([type, undefinedType, nullType]); + } + function getNonNullableType(type: Type): Type { return strictNullChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type; } @@ -10097,22 +10218,11 @@ namespace ts { } function inferTypes(typeVariables: TypeVariable[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) { - let sourceStack: Type[]; - let targetStack: Type[]; - let depth = 0; + let symbolStack: Symbol[]; + let visited: Map; let inferiority = 0; - const visited = createMap(); inferFromTypes(originalSource, originalTarget); - function isInProcess(source: Type, target: Type) { - for (let i = 0; i < depth; i++) { - if (source === sourceStack[i] && target === targetStack[i]) { - return true; - } - } - return false; - } - function inferFromTypes(source: Type, target: Type) { if (!couldContainTypeVariables(target)) { return; @@ -10127,7 +10237,7 @@ namespace ts { } return; } - if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union && !(source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) || + if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union && !(source.flags & TypeFlags.EnumLiteral && target.flags & TypeFlags.EnumLiteral) || source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) { // Source and target are both unions or both intersections. If source and target // are the same type, just relate each constituent type to itself. @@ -10240,26 +10350,29 @@ namespace ts { else { source = getApparentType(source); if (source.flags & TypeFlags.Object) { - if (isInProcess(source, target)) { - return; - } - if (isDeeplyNestedType(source, sourceStack, depth) && isDeeplyNestedType(target, targetStack, depth)) { - return; - } const key = source.id + "," + target.id; - if (visited.get(key)) { + if (visited && visited.get(key)) { return; } - visited.set(key, true); - if (depth === 0) { - sourceStack = []; - targetStack = []; + (visited || (visited = createMap())).set(key, true); + // If we are already processing another target type with the same associated symbol (such as + // an instantiation of the same generic type), we do not explore this target as it would yield + // no further inferences. We exclude the static side of classes from this check since it shares + // its symbol with the instance side which would lead to false positives. + const isNonConstructorObject = target.flags & TypeFlags.Object && + !(getObjectFlags(target) & ObjectFlags.Anonymous && target.symbol && target.symbol.flags & SymbolFlags.Class); + const symbol = isNonConstructorObject ? target.symbol : undefined; + if (symbol) { + if (contains(symbolStack, symbol)) { + return; + } + (symbolStack || (symbolStack = [])).push(symbol); + inferFromObjectTypes(source, target); + symbolStack.pop(); + } + else { + inferFromObjectTypes(source, target); } - sourceStack[depth] = source; - targetStack[depth] = target; - depth++; - inferFromObjectTypes(source, target); - depth--; } } } @@ -10647,15 +10760,16 @@ namespace ts { return strictNullChecks ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts; } if (flags & TypeFlags.StringLiteral) { + const isEmpty = (type).value === ""; return strictNullChecks ? - (type).text === "" ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts : - (type).text === "" ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts; + isEmpty ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts : + isEmpty ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts; } if (flags & (TypeFlags.Number | TypeFlags.Enum)) { return strictNullChecks ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts; } - if (flags & (TypeFlags.NumberLiteral | TypeFlags.EnumLiteral)) { - const isZero = (type).text === "0"; + if (flags & TypeFlags.NumberLiteral) { + const isZero = (type).value === 0; return strictNullChecks ? isZero ? TypeFacts.ZeroStrictFacts : TypeFacts.NonZeroStrictFacts : isZero ? TypeFacts.ZeroFacts : TypeFacts.NonZeroFacts; @@ -10887,7 +11001,7 @@ namespace ts { } return true; } - if (source.flags & TypeFlags.EnumLiteral && target.flags & TypeFlags.Enum && (source).baseType === target) { + if (source.flags & TypeFlags.EnumLiteral && getBaseTypeOfEnumLiteralType(source) === target) { return true; } return containsType(target.types, source); @@ -11891,7 +12005,7 @@ namespace ts { isInAmbientContext(declaration); const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) : type === autoType || type === autoArrayType ? undefinedType : - includeFalsyTypes(type, TypeFlags.Undefined); + getNullableType(type, TypeFlags.Undefined); const flowType = getFlowTypeOfReference(node, type, initialType, flowContainer, !assumeInitialized); // A variable is considered uninitialized when it is possible to analyze the entire control flow graph // from declaration to use, and when the variable's declared type doesn't include undefined but the @@ -12567,7 +12681,7 @@ namespace ts { // corresponding set accessor has a type annotation, return statements in the function are contextually typed if (functionDecl.type || functionDecl.kind === SyntaxKind.Constructor || - functionDecl.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind(functionDecl.symbol, SyntaxKind.SetAccessor))) { + functionDecl.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind(functionDecl.symbol, SyntaxKind.SetAccessor))) { return getReturnTypeOfSignature(getSignatureFromDeclaration(functionDecl)); } @@ -13225,6 +13339,8 @@ namespace ts { if (spread.flags & TypeFlags.Object) { // only set the symbol and flags if this is a (fresh) object type spread.flags |= propagatedFlags; + spread.flags |= TypeFlags.FreshLiteral; + (spread as ObjectType).objectFlags |= ObjectFlags.ObjectLiteral; spread.symbol = node.symbol; } return spread; @@ -13314,6 +13430,7 @@ namespace ts { let spread: Type = emptyObjectType; let attributesArray: Symbol[] = []; let hasSpreadAnyType = false; + let typeToIntersect: Type; let explicitlySpecifyChildrenAttribute = false; const jsxChildrenPropertyName = getJsxElementChildrenPropertyname(); @@ -13345,11 +13462,16 @@ namespace ts { attributesArray = []; attributesTable = createMap(); } - const exprType = getApparentType(checkExpression(attributeDecl.expression)); + const exprType = checkExpression(attributeDecl.expression); if (isTypeAny(exprType)) { hasSpreadAnyType = true; } - spread = getSpreadType(spread, exprType); + if (isValidSpreadType(exprType)) { + spread = getSpreadType(spread, exprType); + } + else { + typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType; + } } } @@ -13404,7 +13526,13 @@ namespace ts { } } - return hasSpreadAnyType ? anyType : createJsxAttributesType(attributes.symbol, attributesTable); + if (hasSpreadAnyType) { + return anyType; + } + + const attributeType = createJsxAttributesType(attributes.symbol, attributesTable); + return typeToIntersect && attributesTable.size ? getIntersectionType([typeToIntersect, attributeType]) : + typeToIntersect ? typeToIntersect : attributeType; /** * Create anonymous type from given attributes symbol table. @@ -13719,7 +13847,7 @@ namespace ts { // Hello World const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements); if (intrinsicElementsType !== unknownType) { - const stringLiteralTypeName = (elementType).text; + const stringLiteralTypeName = (elementType).value; const intrinsicProp = getPropertyOfType(intrinsicElementsType, stringLiteralTypeName); if (intrinsicProp) { return getTypeOfSymbol(intrinsicProp); @@ -14667,7 +14795,7 @@ namespace ts { // If spread arguments are present, check that they correspond to a rest parameter. If so, no // further checking is necessary. if (spreadArgIndex >= 0) { - return isRestParameterIndex(signature, spreadArgIndex); + return isRestParameterIndex(signature, spreadArgIndex) || spreadArgIndex >= signature.minArgumentCount; } // Too many arguments implies incorrect arity. @@ -15082,7 +15210,7 @@ namespace ts { case SyntaxKind.Identifier: case SyntaxKind.NumericLiteral: case SyntaxKind.StringLiteral: - return getLiteralTypeForText(TypeFlags.StringLiteral, (element.name).text); + return getLiteralType((element.name).text); case SyntaxKind.ComputedPropertyName: const nameType = checkComputedPropertyName(element.name); @@ -15994,7 +16122,7 @@ namespace ts { if (strictNullChecks) { const declaration = symbol.valueDeclaration; if (declaration && (declaration).initializer) { - return includeFalsyTypes(type, TypeFlags.Undefined); + return getNullableType(type, TypeFlags.Undefined); } } return type; @@ -16585,7 +16713,7 @@ namespace ts { return silentNeverType; } if (node.operator === SyntaxKind.MinusToken && node.operand.kind === SyntaxKind.NumericLiteral) { - return getFreshTypeOfLiteralType(getLiteralTypeForText(TypeFlags.NumberLiteral, "" + -(node.operand).text)); + return getFreshTypeOfLiteralType(getLiteralType(-(node.operand).text)); } switch (node.operator) { case SyntaxKind.PlusToken: @@ -17093,7 +17221,7 @@ namespace ts { return checkInExpression(left, right, leftType, rightType); case SyntaxKind.AmpersandAmpersandToken: return getTypeFacts(leftType) & TypeFacts.Truthy ? - includeFalsyTypes(rightType, getFalsyFlags(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType))) : + getUnionType([extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) : leftType; case SyntaxKind.BarBarToken: return getTypeFacts(leftType) & TypeFacts.Falsy ? @@ -17265,9 +17393,9 @@ namespace ts { } switch (node.kind) { case SyntaxKind.StringLiteral: - return getFreshTypeOfLiteralType(getLiteralTypeForText(TypeFlags.StringLiteral, (node).text)); + return getFreshTypeOfLiteralType(getLiteralType((node).text)); case SyntaxKind.NumericLiteral: - return getFreshTypeOfLiteralType(getLiteralTypeForText(TypeFlags.NumberLiteral, (node).text)); + return getFreshTypeOfLiteralType(getLiteralType(+(node).text)); case SyntaxKind.TrueKeyword: return trueType; case SyntaxKind.FalseKeyword: @@ -18117,7 +18245,7 @@ namespace ts { // TypeScript 1.0 spec (April 2014): 8.4.3 // Accessors for the same member name must specify the same accessibility. const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const otherAccessor = getDeclarationOfKind(node.symbol, otherKind); + const otherAccessor = getDeclarationOfKind(node.symbol, otherKind); if (otherAccessor) { if ((getModifierFlags(node) & ModifierFlags.AccessibilityModifier) !== (getModifierFlags(otherAccessor) & ModifierFlags.AccessibilityModifier)) { error(node.name, Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility); @@ -18189,7 +18317,7 @@ namespace ts { checkTypeArgumentConstraints(typeParameters, node.typeArguments); } } - if (type.flags & TypeFlags.Enum && !(type).memberTypes && getNodeLinks(node).resolvedSymbol.flags & SymbolFlags.EnumMember) { + if (type.flags & TypeFlags.Enum && getNodeLinks(node).resolvedSymbol.flags & SymbolFlags.EnumMember) { error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type)); } } @@ -20249,7 +20377,7 @@ namespace ts { } function isGetAccessorWithAnnotatedSetAccessor(node: FunctionLikeDeclaration) { - return !!(node.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor))); + return !!(node.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor))); } function isUnwrappedReturnTypeVoidOrAny(func: FunctionLikeDeclaration, returnType: Type): boolean { @@ -20937,7 +21065,7 @@ namespace ts { checkTypeParameterListsIdentical(symbol); // Only check this symbol once - const firstInterfaceDecl = getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); + const firstInterfaceDecl = getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); if (node === firstInterfaceDecl) { const type = getDeclaredTypeOfSymbol(symbol); const typeWithThis = getTypeWithThisArgument(type); @@ -20977,107 +21105,91 @@ namespace ts { function computeEnumMemberValues(node: EnumDeclaration) { const nodeLinks = getNodeLinks(node); - if (!(nodeLinks.flags & NodeCheckFlags.EnumValuesComputed)) { - const enumSymbol = getSymbolOfNode(node); - const enumType = getDeclaredTypeOfSymbol(enumSymbol); - let autoValue = 0; // set to undefined when enum member is non-constant - const ambient = isInAmbientContext(node); - const enumIsConst = isConst(node); - - for (const member of node.members) { - if (isComputedNonLiteralName(member.name)) { - error(member.name, Diagnostics.Computed_property_names_are_not_allowed_in_enums); - } - else { - const text = getTextOfPropertyName(member.name); - if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) { - error(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name); - } - } - - const previousEnumMemberIsNonConstant = autoValue === undefined; - - const initializer = member.initializer; - if (initializer) { - autoValue = computeConstantValueForEnumMemberInitializer(initializer, enumType, enumIsConst, ambient); - } - else if (ambient && !enumIsConst) { - // In ambient enum declarations that specify no const modifier, enum member declarations - // that omit a value are considered computed members (as opposed to having auto-incremented values assigned). - autoValue = undefined; - } - else if (previousEnumMemberIsNonConstant) { - // If the member declaration specifies no value, the member is considered a constant enum member. - // If the member is the first member in the enum declaration, it is assigned the value zero. - // Otherwise, it is assigned the value of the immediately preceding member plus one, - // and an error occurs if the immediately preceding member is not a constant enum member - error(member.name, Diagnostics.Enum_member_must_have_initializer); - } - - if (autoValue !== undefined) { - getNodeLinks(member).enumMemberValue = autoValue; - autoValue++; - } - } - nodeLinks.flags |= NodeCheckFlags.EnumValuesComputed; - } - - function computeConstantValueForEnumMemberInitializer(initializer: Expression, enumType: Type, enumIsConst: boolean, ambient: boolean): number { - // Controls if error should be reported after evaluation of constant value is completed - // Can be false if another more precise error was already reported during evaluation. - let reportError = true; - const value = evalConstant(initializer); - - if (reportError) { - if (value === undefined) { - if (enumIsConst) { - error(initializer, Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression); - } - else if (ambient) { - error(initializer, Diagnostics.In_ambient_enum_declarations_member_initializer_must_be_constant_expression); - } - else { - // Only here do we need to check that the initializer is assignable to the enum type. - checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, /*headMessage*/ undefined); - } - } - else if (enumIsConst) { - if (isNaN(value)) { - error(initializer, Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN); - } - else if (!isFinite(value)) { - error(initializer, Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value); - } - } + let autoValue = 0; + for (const member of node.members) { + const value = computeMemberValue(member, autoValue); + getNodeLinks(member).enumMemberValue = value; + autoValue = typeof value === "number" ? value + 1 : undefined; } + } + } - return value; + function computeMemberValue(member: EnumMember, autoValue: number) { + if (isComputedNonLiteralName(member.name)) { + error(member.name, Diagnostics.Computed_property_names_are_not_allowed_in_enums); + } + else { + const text = getTextOfPropertyName(member.name); + if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) { + error(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name); + } + } + if (member.initializer) { + return computeConstantValue(member); + } + // In ambient enum declarations that specify no const modifier, enum member declarations that omit + // a value are considered computed members (as opposed to having auto-incremented values). + if (isInAmbientContext(member.parent) && !isConst(member.parent)) { + return undefined; + } + // If the member declaration specifies no value, the member is considered a constant enum member. + // If the member is the first member in the enum declaration, it is assigned the value zero. + // Otherwise, it is assigned the value of the immediately preceding member plus one, and an error + // occurs if the immediately preceding member is not a constant enum member. + if (autoValue !== undefined) { + return autoValue; + } + error(member.name, Diagnostics.Enum_member_must_have_initializer); + return undefined; + } - function evalConstant(e: Node): number { - switch (e.kind) { - case SyntaxKind.PrefixUnaryExpression: - const value = evalConstant((e).operand); - if (value === undefined) { - return undefined; - } - switch ((e).operator) { + function computeConstantValue(member: EnumMember): string | number { + const enumKind = getEnumKind(getSymbolOfNode(member.parent)); + const isConstEnum = isConst(member.parent); + const initializer = member.initializer; + const value = enumKind === EnumKind.Literal && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); + if (value !== undefined) { + if (isConstEnum && typeof value === "number" && !isFinite(value)) { + error(initializer, isNaN(value) ? + Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN : + Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value); + } + } + else if (enumKind === EnumKind.Literal) { + error(initializer, Diagnostics.Computed_values_are_not_permitted_in_an_enum_with_string_valued_members); + return 0; + } + else if (isConstEnum) { + error(initializer, Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression); + } + else if (isInAmbientContext(member.parent)) { + error(initializer, Diagnostics.In_ambient_enum_declarations_member_initializer_must_be_constant_expression); + } + else { + // Only here do we need to check that the initializer is assignable to the enum type. + checkTypeAssignableTo(checkExpression(initializer), getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)), initializer, /*headMessage*/ undefined); + } + return value; + + function evaluate(expr: Expression): string | number { + switch (expr.kind) { + case SyntaxKind.PrefixUnaryExpression: + const value = evaluate((expr).operand); + if (typeof value === "number") { + switch ((expr).operator) { case SyntaxKind.PlusToken: return value; case SyntaxKind.MinusToken: return -value; case SyntaxKind.TildeToken: return ~value; } - return undefined; - case SyntaxKind.BinaryExpression: - const left = evalConstant((e).left); - if (left === undefined) { - return undefined; - } - const right = evalConstant((e).right); - if (right === undefined) { - return undefined; - } - switch ((e).operatorToken.kind) { + } + break; + case SyntaxKind.BinaryExpression: + const left = evaluate((expr).left); + const right = evaluate((expr).right); + if (typeof left === "number" && typeof right === "number") { + switch ((expr).operatorToken.kind) { case SyntaxKind.BarToken: return left | right; case SyntaxKind.AmpersandToken: return left & right; case SyntaxKind.GreaterThanGreaterThanToken: return left >> right; @@ -21090,90 +21202,56 @@ namespace ts { case SyntaxKind.MinusToken: return left - right; case SyntaxKind.PercentToken: return left % right; } - return undefined; - case SyntaxKind.NumericLiteral: - checkGrammarNumericLiteral(e); - return +(e).text; - case SyntaxKind.ParenthesizedExpression: - return evalConstant((e).expression); - case SyntaxKind.Identifier: - case SyntaxKind.ElementAccessExpression: - case SyntaxKind.PropertyAccessExpression: - const member = initializer.parent; - const currentType = getTypeOfSymbol(getSymbolOfNode(member.parent)); - let enumType: Type; - let propertyName: string; - - if (e.kind === SyntaxKind.Identifier) { - // unqualified names can refer to member that reside in different declaration of the enum so just doing name resolution won't work. - // instead pick current enum type and later try to fetch member from the type - enumType = currentType; - propertyName = (e).text; + } + break; + case SyntaxKind.StringLiteral: + return (expr).text; + case SyntaxKind.NumericLiteral: + checkGrammarNumericLiteral(expr); + return +(expr).text; + case SyntaxKind.ParenthesizedExpression: + return evaluate((expr).expression); + case SyntaxKind.Identifier: + return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), (expr).text); + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.PropertyAccessExpression: + if (isConstantMemberAccess(expr)) { + const type = getTypeOfExpression((expr).expression); + if (type.symbol && type.symbol.flags & SymbolFlags.Enum) { + const name = expr.kind === SyntaxKind.PropertyAccessExpression ? + (expr).name.text : + ((expr).argumentExpression).text; + return evaluateEnumMember(expr, type.symbol, name); } - else { - let expression: Expression; - if (e.kind === SyntaxKind.ElementAccessExpression) { - if ((e).argumentExpression === undefined || - (e).argumentExpression.kind !== SyntaxKind.StringLiteral) { - return undefined; - } - expression = (e).expression; - propertyName = ((e).argumentExpression).text; - } - else { - expression = (e).expression; - propertyName = (e).name.text; - } + } + break; + } + return undefined; + } - // expression part in ElementAccess\PropertyAccess should be either identifier or dottedName - let current = expression; - while (current) { - if (current.kind === SyntaxKind.Identifier) { - break; - } - else if (current.kind === SyntaxKind.PropertyAccessExpression) { - current = (current).expression; - } - else { - return undefined; - } - } - - enumType = getTypeOfExpression(expression); - // allow references to constant members of other enums - if (!(enumType.symbol && (enumType.symbol.flags & SymbolFlags.Enum))) { - return undefined; - } - } - - if (propertyName === undefined) { - return undefined; - } - - const property = getPropertyOfObjectType(enumType, propertyName); - if (!property || !(property.flags & SymbolFlags.EnumMember)) { - return undefined; - } - - const propertyDecl = property.valueDeclaration; - // self references are illegal - if (member === propertyDecl) { - return undefined; - } - - // illegal case: forward reference - if (!isBlockScopedNameDeclaredBeforeUse(propertyDecl, member)) { - reportError = false; - error(e, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums); - return undefined; - } - - return getNodeLinks(propertyDecl).enumMemberValue; + function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: string) { + const memberSymbol = enumSymbol.exports.get(name); + if (memberSymbol) { + const declaration = memberSymbol.valueDeclaration; + if (declaration !== member) { + if (isBlockScopedNameDeclaredBeforeUse(declaration, member)) { + return getNodeLinks(declaration).enumMemberValue; + } + error(expr, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums); + return 0; } } + return undefined; } } + function isConstantMemberAccess(node: Expression): boolean { + return node.kind === SyntaxKind.Identifier || + node.kind === SyntaxKind.PropertyAccessExpression && isConstantMemberAccess((node).expression) || + node.kind === SyntaxKind.ElementAccessExpression && isConstantMemberAccess((node).expression) && + (node).argumentExpression.kind === SyntaxKind.StringLiteral; + } + function checkEnumDeclaration(node: EnumDeclaration) { if (!produceDiagnostics) { return; @@ -22653,7 +22731,7 @@ namespace ts { const symbolIsUmdExport = symbolFile !== referenceFile; return symbolIsUmdExport ? undefined : symbolFile; } - return findAncestor(node.parent, n => isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol) as ModuleDeclaration | EnumDeclaration; + return findAncestor(node.parent, (n): n is ModuleDeclaration | EnumDeclaration => isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol); } } } @@ -22839,7 +22917,7 @@ namespace ts { return getNodeLinks(node).flags; } - function getEnumMemberValue(node: EnumMember): number { + function getEnumMemberValue(node: EnumMember): string | number { computeEnumMemberValues(node.parent); return getNodeLinks(node).enumMemberValue; } @@ -22854,7 +22932,7 @@ namespace ts { return false; } - function getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number { + function getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number { if (node.kind === SyntaxKind.EnumMember) { return getEnumMemberValue(node); } @@ -22939,7 +23017,7 @@ namespace ts { ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : unknownType; if (flags & TypeFormatFlags.AddUndefined) { - type = includeFalsyTypes(type, TypeFlags.Undefined); + type = getNullableType(type, TypeFlags.Undefined); } getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 5e4afce98c..60553fdab0 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -230,6 +230,8 @@ namespace ts { * If no such value is found, it applies the callback until the parent pointer is undefined or the callback returns "quit" * At that point findAncestor returns undefined. */ + export function findAncestor(node: Node, callback: (element: Node) => element is T): T | undefined; + export function findAncestor(node: Node, callback: (element: Node) => boolean | "quit"): Node | undefined; export function findAncestor(node: Node, callback: (element: Node) => boolean | "quit"): Node { while (node) { const result = callback(node); diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 7c842de277..d68744e973 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -984,7 +984,7 @@ namespace ts { const enumMemberValue = resolver.getConstantValue(node); if (enumMemberValue !== undefined) { write(" = "); - write(enumMemberValue.toString()); + write(getTextOfConstantValue(enumMemberValue)); } write(","); writeLine(); @@ -1840,7 +1840,7 @@ namespace ts { function writeReferencePath(referencedFile: SourceFile, addBundledFileReference: boolean, emitOnlyDtsFiles: boolean): boolean { let declFileName: string; let addedBundledEmitReference = false; - if (isDeclarationFile(referencedFile)) { + if (referencedFile.isDeclarationFile) { // Declaration file, use declaration file name declFileName = referencedFile.fileName; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 14aea1bcd7..8defed492f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1855,25 +1855,29 @@ "category": "Error", "code": 2552 }, - "Expected {0} arguments, but got {1}.": { + "Computed values are not permitted in an enum with string valued members.": { "category": "Error", "code": 2553 }, - "Expected at least {0} arguments, but got {1}.": { + "Expected {0} arguments, but got {1}.": { "category": "Error", "code": 2554 }, + "Expected at least {0} arguments, but got {1}.": { + "category": "Error", + "code": 2555 + }, "Expected {0} arguments, but got a minimum of {1}.": { "category": "Error", "code": 2555 }, "Expected at least {0} arguments, but got a minimum of {1}.": { "category": "Error", - "code": 2556 + "code": 2557 }, "Expected {0} type arguments, but got {1}.": { "category": "Error", - "code": 2557 + "code": 2558 }, "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 76423e45bd..e5ff7de835 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -153,7 +153,7 @@ namespace ts { for (let i = 0; i < numNodes; i++) { const currentNode = bundle ? bundle.sourceFiles[i] : node; const sourceFile = isSourceFile(currentNode) ? currentNode : currentSourceFile; - const shouldSkip = compilerOptions.noEmitHelpers || (sourceFile && getExternalHelpersModuleName(sourceFile) !== undefined); + const shouldSkip = compilerOptions.noEmitHelpers || getExternalHelpersModuleName(sourceFile) !== undefined; const shouldBundle = isSourceFile(currentNode) && !isOwnFileEmit; const helpers = getEmitHelpers(currentNode); if (helpers) { @@ -212,7 +212,7 @@ namespace ts { emitLeadingCommentsOfPosition, } = comments; - let currentSourceFile: SourceFile; + let currentSourceFile: SourceFile | undefined; let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes. let autoGeneratedIdToGeneratedName: string[]; // Map of generated names for temp and loop variables. let generatedNames: Map; // Set of names generated by the NameGenerator. @@ -264,7 +264,12 @@ namespace ts { return endPrint(); } - function writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, output: EmitTextWriter) { + /** + * If `sourceFile` is `undefined`, `node` must be a synthesized `TypeNode`. + */ + function writeNode(hint: EmitHint, node: TypeNode, sourceFile: undefined, output: EmitTextWriter): void; + function writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, output: EmitTextWriter): void; + function writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, output: EmitTextWriter) { const previousWriter = writer; setWriter(output); print(hint, node, sourceFile); @@ -305,8 +310,10 @@ namespace ts { return text; } - function print(hint: EmitHint, node: Node, sourceFile: SourceFile) { - setSourceFile(sourceFile); + function print(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined) { + if (sourceFile) { + setSourceFile(sourceFile); + } pipelineEmitWithNotification(hint, node); } @@ -781,6 +788,7 @@ namespace ts { function emitIdentifier(node: Identifier) { write(getTextOfNode(node, /*includeTrivia*/ false)); + emitTypeArguments(node, node.typeArguments); } // @@ -815,6 +823,7 @@ namespace ts { function emitTypeParameter(node: TypeParameterDeclaration) { emit(node.name); emitWithPrefix(" extends ", node.constraint); + emitWithPrefix(" = ", node.default); } function emitParameter(node: ParameterDeclaration) { @@ -955,7 +964,10 @@ namespace ts { function emitTypeLiteral(node: TypeLiteralNode) { write("{"); - emitList(node, node.members, ListFormat.TypeLiteralMembers); + // If the literal is empty, do not add spaces between braces. + if (node.members.length > 0) { + emitList(node, node.members, getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTypeLiteralMembers : ListFormat.MultiLineTypeLiteralMembers); + } write("}"); } @@ -1002,9 +1014,15 @@ namespace ts { } function emitMappedType(node: MappedTypeNode) { + const emitFlags = getEmitFlags(node); write("{"); - writeLine(); - increaseIndent(); + if (emitFlags & EmitFlags.SingleLine) { + write(" "); + } + else { + writeLine(); + increaseIndent(); + } writeIfPresent(node.readonlyToken, "readonly "); write("["); emit(node.typeParameter.name); @@ -1015,8 +1033,13 @@ namespace ts { write(": "); emit(node.type); write(";"); - writeLine(); - decreaseIndent(); + if (emitFlags & EmitFlags.SingleLine) { + write(" "); + } + else { + writeLine(); + decreaseIndent(); + } write("}"); } @@ -1035,7 +1058,7 @@ namespace ts { } else { write("{"); - emitList(node, elements, ListFormat.ObjectBindingPatternElements); + emitList(node, elements, getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.ObjectBindingPatternElements : ListFormat.ObjectBindingPatternElementsWithSpaceBetweenBraces); write("}"); } } @@ -1131,7 +1154,7 @@ namespace ts { // check if constant enum value is integer const constantValue = getConstantValue(expression); // isFinite handles cases when constantValue is undefined - return isFinite(constantValue) + return typeof constantValue === "number" && isFinite(constantValue) && Math.floor(constantValue) === constantValue && printerOptions.removeComments; } @@ -2637,7 +2660,9 @@ namespace ts { if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { const textSourceNode = (node).textSourceNode; if (isIdentifier(textSourceNode)) { - return "\"" + escapeNonAsciiCharacters(escapeString(getTextOfNode(textSourceNode))) + "\""; + return getEmitFlags(node) & EmitFlags.NoAsciiEscaping ? + `"${escapeString(getTextOfNode(textSourceNode))}"` : + `"${escapeNonAsciiString(getTextOfNode(textSourceNode))}"`; } else { return getLiteralTextOfNode(textSourceNode); @@ -2950,11 +2975,14 @@ namespace ts { // Precomputed Formats Modifiers = SingleLine | SpaceBetweenSiblings, HeritageClauses = SingleLine | SpaceBetweenSiblings, - TypeLiteralMembers = MultiLine | Indented, + SingleLineTypeLiteralMembers = SingleLine | SpaceBetweenBraces | SpaceBetweenSiblings | Indented, + MultiLineTypeLiteralMembers = MultiLine | Indented, + TupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented, UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine, IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine, - ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings, + ObjectBindingPatternElements = SingleLine | CommaDelimited | SpaceBetweenSiblings, + ObjectBindingPatternElementsWithSpaceBetweenBraces = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings, ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings, ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces, ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets, diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 42f6a1267b..63c2028c42 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -107,15 +107,27 @@ namespace ts { // Identifiers - export function createIdentifier(text: string): Identifier { + export function createIdentifier(text: string): Identifier; + /* @internal */ + export function createIdentifier(text: string, typeArguments: TypeNode[]): Identifier; + export function createIdentifier(text: string, typeArguments?: TypeNode[]): Identifier { const node = createSynthesizedNode(SyntaxKind.Identifier); node.text = escapeIdentifier(text); node.originalKeywordKind = text ? stringToToken(text) : SyntaxKind.Unknown; node.autoGenerateKind = GeneratedIdentifierKind.None; node.autoGenerateId = 0; + if (typeArguments) { + node.typeArguments = createNodeArray(typeArguments); + } return node; } + export function updateIdentifier(node: Identifier, typeArguments: NodeArray | undefined): Identifier { + return node.typeArguments !== typeArguments + ? updateNode(createIdentifier(node.text, typeArguments), node) + : node; + } + let nextAutoGenerateId = 0; /** Create a unique temporary variable. */ @@ -271,8 +283,9 @@ namespace ts { // Type Elements - export function createPropertySignature(name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature { + export function createPropertySignature(modifiers: Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature { const node = createSynthesizedNode(SyntaxKind.PropertySignature) as PropertySignature; + node.modifiers = asNodeArray(modifiers); node.name = asName(name); node.questionToken = questionToken; node.type = type; @@ -280,12 +293,13 @@ namespace ts { return node; } - export function updatePropertySignature(node: PropertySignature, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { - return node.name !== name + export function updatePropertySignature(node: PropertySignature, modifiers: Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { + return node.modifiers !== modifiers + || node.name !== name || node.questionToken !== questionToken || node.type !== type || node.initializer !== initializer - ? updateNode(createPropertySignature(name, questionToken, type, initializer), node) + ? updateNode(createPropertySignature(modifiers, name, questionToken, type, initializer), node) : node; } @@ -492,7 +506,7 @@ namespace ts { export function createTypeReferenceNode(typeName: string | EntityName, typeArguments: TypeNode[] | undefined) { const node = createSynthesizedNode(SyntaxKind.TypeReference) as TypeReferenceNode; node.typeName = asName(typeName); - node.typeArguments = asNodeArray(typeArguments); + node.typeArguments = typeArguments && parenthesizeTypeParameters(typeArguments); return node; } @@ -545,7 +559,7 @@ namespace ts { export function createArrayTypeNode(elementType: TypeNode) { const node = createSynthesizedNode(SyntaxKind.ArrayType) as ArrayTypeNode; - node.elementType = elementType; + node.elementType = parenthesizeElementTypeMember(elementType); return node; } @@ -585,7 +599,7 @@ namespace ts { export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: TypeNode[]) { const node = createSynthesizedNode(kind) as UnionTypeNode | IntersectionTypeNode; - node.types = createNodeArray(types); + node.types = parenthesizeElementTypeMembers(types); return node; } @@ -614,7 +628,7 @@ namespace ts { export function createTypeOperatorNode(type: TypeNode) { const node = createSynthesizedNode(SyntaxKind.TypeOperator) as TypeOperatorNode; node.operator = SyntaxKind.KeyOfKeyword; - node.type = type; + node.type = parenthesizeElementTypeMember(type); return node; } @@ -624,7 +638,7 @@ namespace ts { export function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) { const node = createSynthesizedNode(SyntaxKind.IndexedAccessType) as IndexedAccessTypeNode; - node.objectType = objectType; + node.objectType = parenthesizeElementTypeMember(objectType); node.indexType = indexType; return node; } @@ -2357,7 +2371,7 @@ namespace ts { /** * Sets the constant value to emit for an expression. */ - export function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: number) { + export function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number) { const emitNode = getOrCreateEmitNode(node); emitNode.constantValue = value; return node; @@ -2489,6 +2503,25 @@ namespace ts { /* @internal */ namespace ts { + export const nullTransformationContext: TransformationContext = { + enableEmitNotification: noop, + enableSubstitution: noop, + endLexicalEnvironment: () => undefined, + getCompilerOptions: notImplemented, + getEmitHost: notImplemented, + getEmitResolver: notImplemented, + hoistFunctionDeclaration: noop, + hoistVariableDeclaration: noop, + isEmitNotificationEnabled: notImplemented, + isSubstitutionEnabled: notImplemented, + onEmitNode: noop, + onSubstituteNode: notImplemented, + readEmitHelpers: notImplemented, + requestEmitHelper: noop, + resumeLexicalEnvironment: noop, + startLexicalEnvironment: noop, + suspendLexicalEnvironment: noop + }; // Compound nodes @@ -3289,16 +3322,6 @@ namespace ts { return statements; } - export function parenthesizeConditionalHead(condition: Expression) { - const conditionalPrecedence = getOperatorPrecedence(SyntaxKind.ConditionalExpression, SyntaxKind.QuestionToken); - const emittedCondition = skipPartiallyEmittedExpressions(condition); - const conditionPrecedence = getExpressionPrecedence(emittedCondition); - if (compareValues(conditionPrecedence, conditionalPrecedence) === Comparison.LessThan) { - return createParen(condition); - } - return condition; - } - /** * Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended * order of operations. @@ -3600,6 +3623,35 @@ namespace ts { return expression; } + export function parenthesizeElementTypeMember(member: TypeNode) { + switch (member.kind) { + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + return createParenthesizedType(member); + } + return member; + } + + export function parenthesizeElementTypeMembers(members: TypeNode[]) { + return createNodeArray(sameMap(members, parenthesizeElementTypeMember)); + } + + export function parenthesizeTypeParameters(typeParameters: TypeNode[]) { + if (some(typeParameters)) { + const nodeArray = createNodeArray() as NodeArray; + for (let i = 0; i < typeParameters.length; ++i) { + const entry = typeParameters[i]; + nodeArray.push(i === 0 && isFunctionOrConstructorTypeNode(entry) && entry.typeParameters ? + createParenthesizedType(entry) : + entry); + } + + return nodeArray; + } + } + /** * Clones a series of not-emitted expressions with a new inner expression. * @@ -3806,7 +3858,7 @@ namespace ts { if (file.moduleName) { return createLiteral(file.moduleName); } - if (!isDeclarationFile(file) && (options.out || options.outFile)) { + if (!file.isDeclarationFile && (options.out || options.outFile)) { return createLiteral(getExternalModuleNameFromPath(host, file.fileName)); } return undefined; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index dd189784a1..2d9806bcbf 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -23,19 +23,19 @@ namespace ts { } } - function visitNode(cbNode: (node: Node) => T, node: Node): T { + function visitNode(cbNode: (node: Node) => T, node: Node): T | undefined { if (node) { return cbNode(node); } } - function visitNodeArray(cbNodes: (nodes: Node[]) => T, nodes: Node[]) { + function visitNodeArray(cbNodes: (nodes: Node[]) => T, nodes: Node[]): T | undefined { if (nodes) { return cbNodes(nodes); } } - function visitEachNode(cbNode: (node: Node) => T, nodes: Node[]) { + function visitEachNode(cbNode: (node: Node) => T, nodes: Node[]): T | undefined { if (nodes) { for (const node of nodes) { const result = cbNode(node); @@ -50,7 +50,7 @@ namespace ts { // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. - export function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T { + export function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T | undefined { if (!node) { return; } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 8233ab4802..2fde21afec 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1309,7 +1309,7 @@ namespace ts { } function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] { - return isDeclarationFile(sourceFile) ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); + return sourceFile.isDeclarationFile ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } function getOptionsDiagnostics(): Diagnostic[] { @@ -1348,7 +1348,6 @@ namespace ts { const isJavaScriptFile = isSourceFileJavaScript(file); const isExternalModuleFile = isExternalModule(file); - const isDtsFile = isDeclarationFile(file); let imports: LiteralExpression[]; let moduleAugmentations: LiteralExpression[]; @@ -1401,7 +1400,7 @@ namespace ts { } break; case SyntaxKind.ModuleDeclaration: - if (isAmbientModule(node) && (inAmbientModule || hasModifier(node, ModifierFlags.Ambient) || isDeclarationFile(file))) { + if (isAmbientModule(node) && (inAmbientModule || hasModifier(node, ModifierFlags.Ambient) || file.isDeclarationFile)) { const moduleName = (node).name; // Ambient module declarations can be interpreted as augmentations for some existing external modules. // This will happen in two cases: @@ -1412,7 +1411,7 @@ namespace ts { (moduleAugmentations || (moduleAugmentations = [])).push(moduleName); } else if (!inAmbientModule) { - if (isDtsFile) { + if (file.isDeclarationFile) { // for global .d.ts files record name of ambient module (ambientModules || (ambientModules = [])).push(moduleName.text); } @@ -1730,7 +1729,7 @@ namespace ts { const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory)); for (const sourceFile of sourceFiles) { - if (!isDeclarationFile(sourceFile)) { + if (!sourceFile.isDeclarationFile) { const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); @@ -1843,13 +1842,13 @@ namespace ts { const languageVersion = options.target || ScriptTarget.ES3; const outFile = options.outFile || options.out; - const firstNonAmbientExternalModuleSourceFile = forEach(files, f => isExternalModule(f) && !isDeclarationFile(f) ? f : undefined); + const firstNonAmbientExternalModuleSourceFile = forEach(files, f => isExternalModule(f) && !f.isDeclarationFile ? f : undefined); if (options.isolatedModules) { if (options.module === ModuleKind.None && languageVersion < ScriptTarget.ES2015) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher)); } - const firstNonExternalModuleSourceFile = forEach(files, f => !isExternalModule(f) && !isDeclarationFile(f) ? f : undefined); + const firstNonExternalModuleSourceFile = forEach(files, f => !isExternalModule(f) && !f.isDeclarationFile ? f : undefined); if (firstNonExternalModuleSourceFile) { const span = getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile); programDiagnostics.add(createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided)); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 659c2f416a..d27bbf879f 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -712,11 +712,11 @@ namespace ts { return accumulator; } - export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) { + export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined { return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state); } - export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) { + export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined { return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state); } @@ -746,10 +746,11 @@ namespace ts { } /** Optionally, get the shebang */ - export function getShebang(text: string): string { - return shebangTriviaRegex.test(text) - ? shebangTriviaRegex.exec(text)[0] - : undefined; + export function getShebang(text: string): string | undefined { + const match = shebangTriviaRegex.exec(text); + if (match) { + return match[0]; + } } export function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean { diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index bb1732b57e..75f9c43c6f 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -165,7 +165,7 @@ namespace ts { }; function transformRoot(node: T) { - return node && (!isSourceFile(node) || !isDeclarationFile(node)) ? transformation(node) : node; + return node && (!isSourceFile(node) || !node.isDeclarationFile) ? transformation(node) : node; } /** diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index ad9a6b9939..63c1014516 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -295,7 +295,7 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node)) { + if (node.isDeclarationFile) { return node; } diff --git a/src/compiler/transformers/es2016.ts b/src/compiler/transformers/es2016.ts index 1118e6ad9b..a946899177 100644 --- a/src/compiler/transformers/es2016.ts +++ b/src/compiler/transformers/es2016.ts @@ -9,7 +9,7 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node)) { + if (node.isDeclarationFile) { return node; } diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index 3bbb3b3123..3565547d78 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -47,7 +47,7 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node)) { + if (node.isDeclarationFile) { return node; } diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index fef1b009ba..6e2f70b5c3 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -33,7 +33,7 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node)) { + if (node.isDeclarationFile) { return node; } @@ -929,8 +929,8 @@ namespace ts { text: ` var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; ` }; diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 286892f9d3..9aadd6bc68 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -293,8 +293,7 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node) - || (node.transformFlags & TransformFlags.ContainsGenerator) === 0) { + if (node.isDeclarationFile || (node.transformFlags & TransformFlags.ContainsGenerator) === 0) { return node; } diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index e9455490a5..09f361d1b1 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -15,7 +15,7 @@ namespace ts { * @param node A SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node)) { + if (node.isDeclarationFile) { return node; } diff --git a/src/compiler/transformers/module/es2015.ts b/src/compiler/transformers/module/es2015.ts index 660293e074..3951d08109 100644 --- a/src/compiler/transformers/module/es2015.ts +++ b/src/compiler/transformers/module/es2015.ts @@ -16,7 +16,7 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node)) { + if (node.isDeclarationFile) { return node; } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index d387a1a3a2..b3e544a3f8 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -55,7 +55,7 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node) || !(isExternalModule(node) || compilerOptions.isolatedModules)) { + if (node.isDeclarationFile || !(isExternalModule(node) || compilerOptions.isolatedModules)) { return node; } diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 5711d9f111..3355ad3563 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -50,9 +50,7 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node) - || !(isExternalModule(node) - || compilerOptions.isolatedModules)) { + if (node.isDeclarationFile || !(isExternalModule(node) || compilerOptions.isolatedModules)) { return node; } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 6597840922..cc7f89acfb 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -76,7 +76,7 @@ namespace ts { * @param node A SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node)) { + if (node.isDeclarationFile) { return node; } @@ -2494,22 +2494,27 @@ namespace ts { // we pass false as 'generateNameForComputedPropertyName' for a backward compatibility purposes // old emitter always generate 'expression' part of the name as-is. const name = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ false); + const valueExpression = transformEnumMemberDeclarationValue(member); + const innerAssignment = createAssignment( + createElementAccess( + currentNamespaceContainerName, + name + ), + valueExpression + ); + const outerAssignment = valueExpression.kind === SyntaxKind.StringLiteral ? + innerAssignment : + createAssignment( + createElementAccess( + currentNamespaceContainerName, + innerAssignment + ), + name + ); return setTextRange( createStatement( setTextRange( - createAssignment( - createElementAccess( - currentNamespaceContainerName, - createAssignment( - createElementAccess( - currentNamespaceContainerName, - name - ), - transformEnumMemberDeclarationValue(member) - ) - ), - name - ), + outerAssignment, member ) ), @@ -3349,7 +3354,7 @@ namespace ts { return node; } - function tryGetConstEnumValue(node: Node): number { + function tryGetConstEnumValue(node: Node): string | number { if (compilerOptions.isolatedModules) { return undefined; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 67d80a92ce..a623da1f46 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -577,10 +577,11 @@ namespace ts { * If the identifier begins with two underscores, this will begin with three. */ text: string; - originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later + originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later /*@internal*/ autoGenerateKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier. - /*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name. - isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace + /*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name. + isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace + /*@internal*/ typeArguments?: NodeArray; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics. } // Transient identifier node (marked by id === -1) @@ -2527,11 +2528,11 @@ namespace ts { indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): IndexSignatureDeclaration; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; - getSymbolAtLocation(node: Node): Symbol; + getSymbolAtLocation(node: Node): Symbol | undefined; getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; - getShorthandAssignmentValueSymbol(location: Node): Symbol; - getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol; - getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol; + getShorthandAssignmentValueSymbol(location: Node): Symbol | undefined; + getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol | undefined; + getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined; getTypeAtLocation(node: Node): Type; getTypeFromTypeNode(node: TypeNode): Type; signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; @@ -2542,15 +2543,15 @@ namespace ts { getAugmentedPropertiesOfType(type: Type): Symbol[]; getRootSymbols(symbol: Symbol): Symbol[]; getContextualType(node: Expression): Type | undefined; - getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature; - getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature; - isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; + getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature | undefined; + getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; + isImplementationOfOverload(node: FunctionLikeDeclaration): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; isArgumentsSymbol(symbol: Symbol): boolean; isUnknownSymbol(symbol: Symbol): boolean; /* @internal */ getMergedSymbol(symbol: Symbol): Symbol; - getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; + getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined; isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean; /** Follow all aliases to get the original symbol. */ getAliasedSymbol(symbol: Symbol): Symbol; @@ -2560,7 +2561,7 @@ namespace ts { /** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */ /* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[]; - getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type; + getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined; getJsxIntrinsicTagNames(): Symbol[]; isOptionalParameter(node: ParameterDeclaration): boolean; getAmbientModules(): Symbol[]; @@ -2568,10 +2569,10 @@ namespace ts { tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined; getApparentType(type: Type): Type; getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): string | undefined; - getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string; - /* @internal */ getBaseConstraintOfType(type: Type): Type; + getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined; + /* @internal */ getBaseConstraintOfType(type: Type): Type | undefined; - /* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol; + /* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol | undefined; // Should not be called directly. Should only be accessed through the Program instance. /* @internal */ getDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; @@ -2586,24 +2587,39 @@ namespace ts { /** * For a union, will include a property if it's defined in *any* of the member types. * So for `{ a } | { b }`, this will include both `a` and `b`. + * Does not include properties of primitive types. */ /* @internal */ getAllPossiblePropertiesOfType(type: Type): Symbol[]; } export enum NodeBuilderFlags { None = 0, - allowThisInObjectLiteral = 1 << 0, - allowQualifedNameInPlaceOfIdentifier = 1 << 1, - allowTypeParameterInQualifiedName = 1 << 2, - allowAnonymousIdentifier = 1 << 3, - allowEmptyUnionOrIntersection = 1 << 4, - allowEmptyTuple = 1 << 5 + // Options + NoTruncation = 1 << 0, // Don't truncate result + WriteArrayAsGenericType = 1 << 1, // Write Array instead T[] + WriteTypeArgumentsOfSignature = 1 << 5, // Write the type arguments instead of type parameters of the signature + UseFullyQualifiedType = 1 << 6, // Write out the fully qualified type name (eg. Module.Type, instead of Type) + SuppressAnyReturnType = 1 << 8, // If the return type is any-like, don't offer a return type. + WriteTypeParametersInQualifiedName = 1 << 9, + + // Error handling + AllowThisInObjectLiteral = 1 << 10, + AllowQualifedNameInPlaceOfIdentifier = 1 << 11, + AllowAnonymousIdentifier = 1 << 13, + AllowEmptyUnionOrIntersection = 1 << 14, + AllowEmptyTuple = 1 << 15, + + IgnoreErrors = AllowThisInObjectLiteral | AllowQualifedNameInPlaceOfIdentifier | AllowAnonymousIdentifier | AllowEmptyUnionOrIntersection | AllowEmptyTuple, + + // State + InObjectTypeLiteral = 1 << 20, + InTypeAlias = 1 << 23, // Writing type in type alias declaration } export interface SymbolDisplayBuilder { buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; - buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; + buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; @@ -2753,7 +2769,7 @@ namespace ts { getNodeCheckFlags(node: Node): NodeCheckFlags; isDeclarationVisible(node: Declaration): boolean; collectLinkedAliases(node: Identifier): Node[]; - isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; + isImplementationOfOverload(node: FunctionLikeDeclaration): boolean | undefined; isRequiredInitializedParameter(node: ParameterDeclaration): boolean; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; @@ -2761,7 +2777,7 @@ namespace ts { isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult; // Returns the constant value this property access resolves to, or 'undefined' for a non-constant - getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; + getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number; getReferencedValueDeclaration(reference: Identifier): Declaration; getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind; isOptionalParameter(node: ParameterDeclaration): boolean; @@ -2899,6 +2915,13 @@ namespace ts { isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration bindingElement?: BindingElement; // Binding element associated with property symbol exportsSomeValue?: boolean; // True if module exports some value (not just types) + enumKind?: EnumKind; // Enum declaration classification + } + + /* @internal */ + export const enum EnumKind { + Numeric, // Numeric enum (each member has a TypeFlags.Enum type) + Literal // Literal enum (each member has a TypeFlags.EnumLiteral type) } /* @internal */ @@ -2971,7 +2994,7 @@ namespace ts { resolvedSymbol?: Symbol; // Cached name resolution result resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result maybeTypePredicate?: boolean; // Cached check whether call expression might reference a type predicate - enumMemberValue?: number; // Constant value of enum member + enumMemberValue?: string | number; // Constant value of enum member isVisible?: boolean; // Is this node visible containsArgumentsReference?: boolean; // Whether a function-like declaration contains an 'arguments' reference hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context @@ -2991,7 +3014,7 @@ namespace ts { StringLiteral = 1 << 5, NumberLiteral = 1 << 6, BooleanLiteral = 1 << 7, - EnumLiteral = 1 << 8, + EnumLiteral = 1 << 8, // Always combined with StringLiteral, NumberLiteral, or Union ESSymbol = 1 << 9, // Type of symbol primitive introduced in ES6 Void = 1 << 10, Undefined = 1 << 11, @@ -3017,7 +3040,7 @@ namespace ts { /* @internal */ Nullable = Undefined | Null, - Literal = StringLiteral | NumberLiteral | BooleanLiteral | EnumLiteral, + Literal = StringLiteral | NumberLiteral | BooleanLiteral, StringOrNumberLiteral = StringLiteral | NumberLiteral, /* @internal */ DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null, @@ -3025,9 +3048,9 @@ namespace ts { /* @internal */ Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive, /* @internal */ - Primitive = String | Number | Boolean | Enum | ESSymbol | Void | Undefined | Null | Literal, + Primitive = String | Number | Boolean | Enum | EnumLiteral | ESSymbol | Void | Undefined | Null | Literal, StringLike = String | StringLiteral | Index, - NumberLike = Number | NumberLiteral | Enum | EnumLiteral, + NumberLike = Number | NumberLiteral | Enum, BooleanLike = Boolean | BooleanLiteral, EnumLike = Enum | EnumLiteral, UnionOrIntersection = Union | Intersection, @@ -3066,19 +3089,21 @@ namespace ts { // String literal types (TypeFlags.StringLiteral) // Numeric literal types (TypeFlags.NumberLiteral) export interface LiteralType extends Type { - text: string; // Text of literal + value: string | number; // Value of literal freshType?: LiteralType; // Fresh version of type regularType?: LiteralType; // Regular version of type } - // Enum types (TypeFlags.Enum) - export interface EnumType extends Type { - memberTypes: EnumLiteralType[]; + export interface StringLiteralType extends LiteralType { + value: string; } - // Enum types (TypeFlags.EnumLiteral) - export interface EnumLiteralType extends LiteralType { - baseType: EnumType & UnionType; // Base enum type + export interface NumberLiteralType extends LiteralType { + value: number; + } + + // Enum types (TypeFlags.Enum) + export interface EnumType extends Type { } export const enum ObjectFlags { @@ -3135,7 +3160,7 @@ namespace ts { */ export interface TypeReference extends ObjectType { target: GenericType; // Type reference target - typeArguments: Type[]; // Type reference type arguments (undefined if none) + typeArguments?: Type[]; // Type reference type arguments (undefined if none) } // Generic class and interface types @@ -3265,7 +3290,7 @@ namespace ts { export interface Signature { declaration: SignatureDeclaration; // Originating declaration - typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) + typeParameters?: TypeParameter[]; // Type parameters (undefined if non-generic) parameters: Symbol[]; // Parameters /* @internal */ thisParameter?: Symbol; // symbol of this-type parameter @@ -3527,7 +3552,7 @@ namespace ts { export const enum NewLineKind { CarriageReturnLineFeed = 0, - LineFeed = 1, + LineFeed = 1 } export interface LineAndCharacter { @@ -3946,7 +3971,7 @@ namespace ts { commentRange?: TextRange; // The text range to use when emitting leading or trailing comments sourceMapRange?: TextRange; // The text range to use when emitting leading or trailing source mappings tokenSourceMapRanges?: TextRange[]; // The text range to use when emitting source mappings for tokens - constantValue?: number; // The constant value of an expression + constantValue?: string | number; // The constant value of an expression externalHelpersModuleName?: Identifier; // The local name for an imported helpers module helpers?: EmitHelper[]; // Emit helpers for the node } @@ -3979,6 +4004,7 @@ namespace ts { NoHoisting = 1 << 21, // Do not hoist this declaration in --module system HasEndOfDeclarationMarker = 1 << 22, // Declaration has an associated NotEmittedStatement to mark the end of the declaration Iterator = 1 << 23, // The expression to a `yield*` should be treated as an Iterator when down-leveling, not an Iterable. + NoAsciiEscaping = 1 << 24, // When synthesizing nodes that lack an original node or textSourceNode, we want to write the text on the node with ASCII escaping substitutions. } export interface EmitHelper { @@ -4191,7 +4217,7 @@ namespace ts { * Prints a bundle of source files as-is, without any emit transformations. */ printBundle(bundle: Bundle): string; - /*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, writer: EmitTextWriter): void; + /*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void; /*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void; /*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter): void; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 58a1822a24..2b6831f881 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -11,12 +11,12 @@ namespace ts { isTypeReferenceDirective?: boolean; } - export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration { + export function getDeclarationOfKind(symbol: Symbol, kind: T["kind"]): T { const declarations = symbol.declarations; if (declarations) { for (const declaration of declarations) { if (declaration.kind === kind) { - return declaration; + return declaration as T; } } } @@ -328,19 +328,21 @@ namespace ts { return getSourceTextOfNodeFromSourceFile(sourceFile, node); } + const escapeText = getEmitFlags(node) & EmitFlags.NoAsciiEscaping ? escapeString : escapeNonAsciiString; + // If we can't reach the original source text, use the canonical form if it's a number, - // or an escaped quoted form of the original text if it's string-like. + // or a (possibly escaped) quoted form of the original text if it's string-like. switch (node.kind) { case SyntaxKind.StringLiteral: - return getQuotedEscapedLiteralText('"', node.text, '"'); + return '"' + escapeText(node.text) + '"'; case SyntaxKind.NoSubstitutionTemplateLiteral: - return getQuotedEscapedLiteralText("`", node.text, "`"); + return "`" + escapeText(node.text) + "`"; case SyntaxKind.TemplateHead: - return getQuotedEscapedLiteralText("`", node.text, "${"); + return "`" + escapeText(node.text) + "${"; case SyntaxKind.TemplateMiddle: - return getQuotedEscapedLiteralText("}", node.text, "${"); + return "}" + escapeText(node.text) + "${"; case SyntaxKind.TemplateTail: - return getQuotedEscapedLiteralText("}", node.text, "`"); + return "}" + escapeText(node.text) + "`"; case SyntaxKind.NumericLiteral: return node.text; } @@ -348,8 +350,8 @@ namespace ts { Debug.fail(`Literal kind '${node.kind}' not accounted for.`); } - function getQuotedEscapedLiteralText(leftQuote: string, text: string, rightQuote: string) { - return leftQuote + escapeNonAsciiCharacters(escapeString(text)) + rightQuote; + export function getTextOfConstantValue(value: string | number) { + return typeof value === "string" ? '"' + escapeNonAsciiString(value) + '"' : "" + value; } // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' @@ -465,7 +467,7 @@ namespace ts { return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name); } - export function getNameFromIndexInfo(info: IndexInfo) { + export function getNameFromIndexInfo(info: IndexInfo): string | undefined { return info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : undefined; } @@ -589,10 +591,6 @@ namespace ts { return (file.externalModuleIndicator || file.commonJsModuleIndicator) !== undefined; } - export function isDeclarationFile(file: SourceFile): boolean { - return file.isDeclarationFile; - } - export function isConstEnumDeclaration(node: Node): boolean { return node.kind === SyntaxKind.EnumDeclaration && isConst(node); } @@ -881,6 +879,16 @@ namespace ts { return false; } + export function isFunctionOrConstructorTypeNode(node: Node): node is FunctionTypeNode | ConstructorTypeNode { + switch (node.kind) { + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + return true; + } + + return false; + } + export function introducesArgumentsExoticObject(node: Node) { switch (node.kind) { case SyntaxKind.MethodDeclaration: @@ -2462,7 +2470,8 @@ namespace ts { } const nonAsciiCharacters = /[^\u0000-\u007F]/g; - export function escapeNonAsciiCharacters(s: string): string { + export function escapeNonAsciiString(s: string): string { + s = escapeString(s); // Replace non-ASCII characters with '\uNNNN' escapes if any exist. // Otherwise just return the original string. return nonAsciiCharacters.test(s) ? @@ -2566,7 +2575,7 @@ namespace ts { export function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): string { const file = resolver.getExternalModuleFileFromDeclaration(declaration); - if (!file || isDeclarationFile(file)) { + if (!file || file.isDeclarationFile) { return undefined; } return getResolvedExternalModuleName(host, file); @@ -2639,7 +2648,7 @@ namespace ts { /** Don't call this for `--outFile`, just for `--outDir` or plain emit. `--outFile` needs additional checks. */ export function sourceFileMayBeEmitted(sourceFile: SourceFile, options: CompilerOptions, isSourceFileFromExternalLibrary: (file: SourceFile) => boolean) { - return !(options.noEmitForJsFiles && isSourceFileJavaScript(sourceFile)) && !isDeclarationFile(sourceFile) && !isSourceFileFromExternalLibrary(sourceFile); + return !(options.noEmitForJsFiles && isSourceFileJavaScript(sourceFile)) && !sourceFile.isDeclarationFile && !isSourceFileFromExternalLibrary(sourceFile); } /** @@ -3255,13 +3264,13 @@ namespace ts { const carriageReturnLineFeed = "\r\n"; const lineFeed = "\n"; export function getNewLineCharacter(options: CompilerOptions | PrinterOptions): string { - if (options.newLine === NewLineKind.CarriageReturnLineFeed) { - return carriageReturnLineFeed; + switch (options.newLine) { + case NewLineKind.CarriageReturnLineFeed: + return carriageReturnLineFeed; + case NewLineKind.LineFeed: + return lineFeed; } - else if (options.newLine === NewLineKind.LineFeed) { - return lineFeed; - } - else if (sys) { + if (sys) { return sys.newLine; } return carriageReturnLineFeed; @@ -4010,6 +4019,10 @@ namespace ts { return node.kind === SyntaxKind.ImportEqualsDeclaration; } + export function isImportDeclaration(node: Node): node is ImportDeclaration { + return node.kind === SyntaxKind.ImportDeclaration; + } + export function isImportClause(node: Node): node is ImportClause { return node.kind === SyntaxKind.ImportClause; } @@ -4032,6 +4045,10 @@ namespace ts { return node.kind === SyntaxKind.ExportSpecifier; } + export function isExportAssignment(node: Node): node is ExportAssignment { + return node.kind === SyntaxKind.ExportAssignment; + } + export function isModuleOrEnumDeclaration(node: Node): node is ModuleDeclaration | EnumDeclaration { return node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.EnumDeclaration; } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 517854e21c..eb28721a14 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -220,6 +220,10 @@ namespace ts { switch (kind) { // Names + + case SyntaxKind.Identifier: + return updateIdentifier(node, nodesVisitor((node).typeArguments, visitor, isTypeNode)); + case SyntaxKind.QualifiedName: return updateQualifiedName(node, visitNode((node).left, visitor, isEntityName), @@ -255,6 +259,7 @@ namespace ts { case SyntaxKind.PropertySignature: return updatePropertySignature((node), + nodesVisitor((node).modifiers, visitor, isToken), visitNode((node).name, visitor, isPropertyName), visitNode((node).questionToken, tokenVisitor, isToken), visitNode((node).type, visitor, isTypeNode), @@ -970,6 +975,15 @@ namespace ts { break; // Type member + + case SyntaxKind.PropertySignature: + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).questionToken, cbNode, result); + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).initializer, cbNode, result); + break; + case SyntaxKind.PropertyDeclaration: result = reduceNodes((node).decorators, cbNodes, result); result = reduceNodes((node).modifiers, cbNodes, result); diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index b0efcf4c38..28d59fe35b 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -372,7 +372,7 @@ class ProjectRunner extends RunnerBase { const compilerOptions = compilerResult.program.getCompilerOptions(); ts.forEach(compilerResult.program.getSourceFiles(), sourceFile => { - if (ts.isDeclarationFile(sourceFile)) { + if (sourceFile.isDeclarationFile) { allInputFiles.unshift({ emittedFileName: sourceFile.fileName, code: sourceFile.text }); } else if (!(compilerOptions.outFile || compilerOptions.out)) { diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 957112016c..39d8e13dde 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -130,7 +130,7 @@ namespace ts.codefix { } function signatureToMethodDeclaration(signature: Signature, enclosingDeclaration: Node, body?: Block) { - const signatureDeclaration = checker.signatureToSignatureDeclaration(signature, SyntaxKind.MethodDeclaration, enclosingDeclaration); + const signatureDeclaration = checker.signatureToSignatureDeclaration(signature, SyntaxKind.MethodDeclaration, enclosingDeclaration, NodeBuilderFlags.SuppressAnyReturnType); if (signatureDeclaration) { signatureDeclaration.decorators = undefined; signatureDeclaration.modifiers = modifiers; diff --git a/src/services/completions.ts b/src/services/completions.ts index 5bc2a26861..d6772447f5 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -275,7 +275,7 @@ namespace ts.Completions { } } else if (type.flags & TypeFlags.StringLiteral) { - const name = (type).text; + const name = (type).value; if (!uniques.has(name)) { uniques.set(name, true); result.push({ @@ -359,7 +359,7 @@ namespace ts.Completions { start = timestamp(); // Completion not allowed inside comments, bail out if this is the case - const insideComment = isInsideComment(sourceFile, currentToken, position); + const insideComment = isInComment(sourceFile, position, currentToken); log("getCompletionData: Is inside comment: " + (timestamp() - start)); if (insideComment) { diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 395c282f6d..d9deaef9e5 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -550,7 +550,7 @@ namespace ts.FindAllReferences.Core { } function isObjectBindingPatternElementWithoutPropertyName(symbol: Symbol): boolean { - const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); + const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); return bindingElement && bindingElement.parent.kind === SyntaxKind.ObjectBindingPattern && !bindingElement.propertyName; @@ -558,7 +558,7 @@ namespace ts.FindAllReferences.Core { function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol: Symbol, checker: TypeChecker): Symbol | undefined { if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { - const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); + const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); const typeOfPattern = checker.getTypeAtLocation(bindingElement.parent); return typeOfPattern && checker.getPropertyOfType(typeOfPattern, (bindingElement.name).text); } diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index df50f3ec31..c540c44620 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -526,17 +526,18 @@ namespace ts.FindAllReferences { return isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol, exportKind } : undefined; } - function symbolName(symbol: Symbol): string { + function symbolName(symbol: Symbol): string | undefined { if (symbol.name !== "default") { return symbol.name; } - const name = forEach(symbol.declarations, decl => { + return forEach(symbol.declarations, decl => { + if (isExportAssignment(decl)) { + return isIdentifier(decl.expression) ? decl.expression.text : undefined; + } const name = getNameOfDeclaration(decl); return name && name.kind === SyntaxKind.Identifier && name.text; }); - Debug.assert(!!name); - return name; } /** If at an export specifier, go to the symbol it refers to. */ diff --git a/src/services/services.ts b/src/services/services.ts index 1b4678b5db..fdacf9bf9e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -360,6 +360,7 @@ namespace ts { _incrementExpressionBrand: any; _unaryExpressionBrand: any; _expressionBrand: any; + /*@internal*/typeArguments: NodeArray; constructor(_kind: SyntaxKind.Identifier, pos: number, end: number) { super(pos, end); } @@ -1853,8 +1854,8 @@ namespace ts { // OK, we have found a match in the file. This is only an acceptable match if // it is contained within a comment. - const token = getTokenAtPosition(sourceFile, matchPosition); - if (!isInsideComment(sourceFile, token, matchPosition)) { + + if (!isInComment(sourceFile, matchPosition)) { continue; } diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 4268a52c41..67bacaeadd 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -275,7 +275,7 @@ namespace ts.SymbolDisplay { } if (symbolFlags & SymbolFlags.Module) { addNewLineIfDisplayPartsExist(); - const declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); + const declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); const isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; displayParts.push(keywordPart(isNamespace ? SyntaxKind.NamespaceKeyword : SyntaxKind.ModuleKeyword)); displayParts.push(spacePart()); @@ -296,9 +296,9 @@ namespace ts.SymbolDisplay { } else { // Method/function type parameter - let declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter); - Debug.assert(declaration !== undefined); - declaration = declaration.parent; + const decl = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter); + Debug.assert(decl !== undefined); + const declaration = decl.parent; if (declaration) { if (isFunctionLikeKind(declaration.kind)) { @@ -336,7 +336,8 @@ namespace ts.SymbolDisplay { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); displayParts.push(spacePart()); - displayParts.push(displayPart(constantValue.toString(), SymbolDisplayPartKind.numericLiteral)); + displayParts.push(displayPart(getTextOfConstantValue(constantValue), + typeof constantValue === "number" ? SymbolDisplayPartKind.numericLiteral : SymbolDisplayPartKind.stringLiteral)); } } } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 7ff0c37fa9..5a1aaa21bc 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -497,8 +497,8 @@ namespace ts.textChanges { readonly node: Node; } - export function getNonformattedText(node: Node, sourceFile: SourceFile, newLine: NewLineKind): NonFormattedText { - const options = { newLine, target: sourceFile.languageVersion }; + export function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLine: NewLineKind): NonFormattedText { + const options = { newLine, target: sourceFile && sourceFile.languageVersion }; const writer = new Writer(getNewLineCharacter(options)); const printer = createPrinter(options, writer); printer.writeNode(EmitHint.Unspecified, node, sourceFile, writer); @@ -528,26 +528,6 @@ namespace ts.textChanges { return skipTrivia(s, 0) === s.length; } - const nullTransformationContext: TransformationContext = { - enableEmitNotification: noop, - enableSubstitution: noop, - endLexicalEnvironment: () => undefined, - getCompilerOptions: notImplemented, - getEmitHost: notImplemented, - getEmitResolver: notImplemented, - hoistFunctionDeclaration: noop, - hoistVariableDeclaration: noop, - isEmitNotificationEnabled: notImplemented, - isSubstitutionEnabled: notImplemented, - onEmitNode: noop, - onSubstituteNode: notImplemented, - readEmitHelpers: notImplemented, - requestEmitHelper: noop, - resumeLexicalEnvironment: noop, - startLexicalEnvironment: noop, - suspendLexicalEnvironment: noop - }; - function assignPositionsToNode(node: Node): Node { const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); // create proxy node for non synthesized nodes diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 4ae9204f7e..c8b710789a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -256,37 +256,6 @@ namespace ts { getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node; } - /** Returns true if the position is within a comment */ - export function isInsideComment(sourceFile: SourceFile, token: Node, position: number): boolean { - // The position has to be: 1. in the leading trivia (before token.getStart()), and 2. within a comment - return position <= token.getStart(sourceFile) && - (isInsideCommentRange(getTrailingCommentRanges(sourceFile.text, token.getFullStart())) || - isInsideCommentRange(getLeadingCommentRanges(sourceFile.text, token.getFullStart()))); - - function isInsideCommentRange(comments: CommentRange[]): boolean { - return forEach(comments, comment => { - // either we are 1. completely inside the comment, or 2. at the end of the comment - if (comment.pos < position && position < comment.end) { - return true; - } - else if (position === comment.end) { - const text = sourceFile.text; - const width = comment.end - comment.pos; - // is single line comment or just /* - if (width <= 2 || text.charCodeAt(comment.pos + 1) === CharacterCodes.slash) { - return true; - } - else { - // is unterminated multi-line comment - return !(text.charCodeAt(comment.end - 1) === CharacterCodes.slash && - text.charCodeAt(comment.end - 2) === CharacterCodes.asterisk); - } - } - return false; - }); - } - } - export function getContainerNode(node: Node): Declaration { while (true) { node = node.parent; @@ -651,44 +620,26 @@ namespace ts { return current; } - if (includeJsDocComment) { - const jsDocChildren = ts.filter(current.getChildren(), isJSDocNode); - for (const jsDocChild of jsDocChildren) { - const start = allowPositionInLeadingTrivia ? jsDocChild.getFullStart() : jsDocChild.getStart(sourceFile, includeJsDocComment); - if (start <= position) { - const end = jsDocChild.getEnd(); - if (position < end || (position === end && jsDocChild.kind === SyntaxKind.EndOfFileToken)) { - current = jsDocChild; - continue outer; - } - else if (includeItemAtEndPosition && end === position) { - const previousToken = findPrecedingToken(position, sourceFile, jsDocChild); - if (previousToken && includeItemAtEndPosition(previousToken)) { - return previousToken; - } - } - } - } - } - // find the child that contains 'position' for (const child of current.getChildren()) { - // all jsDocComment nodes were already visited - if (isJSDocNode(child)) { + if (isJSDocNode(child) && !includeJsDocComment) { continue; } + const start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, includeJsDocComment); - if (start <= position) { - const end = child.getEnd(); - if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) { - current = child; - continue outer; - } - else if (includeItemAtEndPosition && end === position) { - const previousToken = findPrecedingToken(position, sourceFile, child); - if (previousToken && includeItemAtEndPosition(previousToken)) { - return previousToken; - } + if (start > position) { + continue; + } + + const end = child.getEnd(); + if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) { + current = child; + continue outer; + } + else if (includeItemAtEndPosition && end === position) { + const previousToken = findPrecedingToken(position, sourceFile, child); + if (previousToken && includeItemAtEndPosition(previousToken)) { + return previousToken; } } } @@ -834,10 +785,6 @@ namespace ts { return false; } - export function isInComment(sourceFile: SourceFile, position: number) { - return isInCommentHelper(sourceFile, position, /*predicate*/ undefined); - } - /** * returns true if the position is in between the open and close elements of an JSX expression. */ @@ -883,15 +830,26 @@ namespace ts { } /** - * Returns true if the cursor at position in sourceFile is within a comment that additionally - * satisfies predicate, and false otherwise. + * Returns true if the cursor at position in sourceFile is within a comment. + * + * @param tokenAtPosition Must equal `getTokenAtPosition(sourceFile, position) + * @param predicate Additional predicate to test on the comment range. */ - export function isInCommentHelper(sourceFile: SourceFile, position: number, predicate?: (c: CommentRange) => boolean): boolean { - const token = getTokenAtPosition(sourceFile, position); + export function isInComment(sourceFile: SourceFile, position: number, tokenAtPosition = getTokenAtPosition(sourceFile, position), predicate?: (c: CommentRange) => boolean): boolean { + return position <= tokenAtPosition.getStart(sourceFile) && + (isInCommentRange(getLeadingCommentRanges(sourceFile.text, tokenAtPosition.pos)) || + isInCommentRange(getTrailingCommentRanges(sourceFile.text, tokenAtPosition.pos))); - if (token && position <= token.getStart(sourceFile)) { - const commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); + function isInCommentRange(commentRanges: CommentRange[]): boolean { + return forEach(commentRanges, c => isPositionInCommentRange(c, position, sourceFile.text) && (!predicate || predicate(c))); + } + } + function isPositionInCommentRange({ pos, end, kind }: ts.CommentRange, position: number, text: string): boolean { + if (pos < position && position < end) { + return true; + } + else if (position === end) { // The end marker of a single-line comment does not include the newline character. // In the following case, we are inside a comment (^ denotes the cursor position): // @@ -902,15 +860,13 @@ namespace ts { // /* asdf */^ // // Internally, we represent the end of the comment at the newline and closing '/', respectively. - return predicate ? - forEach(commentRanges, c => c.pos < position && - (c.kind === SyntaxKind.SingleLineCommentTrivia ? position <= c.end : position < c.end) && - predicate(c)) : - forEach(commentRanges, c => c.pos < position && - (c.kind === SyntaxKind.SingleLineCommentTrivia ? position <= c.end : position < c.end)); + return kind === SyntaxKind.SingleLineCommentTrivia || + // true for unterminated multi-line comment + !(text.charCodeAt(end - 1) === CharacterCodes.slash && text.charCodeAt(end - 2) === CharacterCodes.asterisk); + } + else { + return false; } - - return false; } export function hasDocComment(sourceFile: SourceFile, position: number) { @@ -1093,21 +1049,17 @@ namespace ts { } export function isInReferenceComment(sourceFile: SourceFile, position: number): boolean { - return isInCommentHelper(sourceFile, position, isReferenceComment); - - function isReferenceComment(c: CommentRange): boolean { + return isInComment(sourceFile, position, /*tokenAtPosition*/ undefined, c => { const commentText = sourceFile.text.substring(c.pos, c.end); return tripleSlashDirectivePrefixRegex.test(commentText); - } + }); } export function isInNonReferenceComment(sourceFile: SourceFile, position: number): boolean { - return isInCommentHelper(sourceFile, position, isNonReferenceComment); - - function isNonReferenceComment(c: CommentRange): boolean { + return isInComment(sourceFile, position, /*tokenAtPosition*/ undefined, c => { const commentText = sourceFile.text.substring(c.pos, c.end); return !tripleSlashDirectivePrefixRegex.test(commentText); - } + }); } export function createTextSpanFromNode(node: Node, sourceFile?: SourceFile): TextSpan { diff --git a/tests/baselines/reference/bestCommonTypeOfTuple.types b/tests/baselines/reference/bestCommonTypeOfTuple.types index 82c96ecb86..d62503b57d 100644 --- a/tests/baselines/reference/bestCommonTypeOfTuple.types +++ b/tests/baselines/reference/bestCommonTypeOfTuple.types @@ -98,8 +98,8 @@ var e3 = t3[2]; // any >2 : 2 var e4 = t4[3]; // number ->e4 : number | E1 | E2 ->t4[3] : number | E1 | E2 +>e4 : number +>t4[3] : number >t4 : [E1, E2, number] >3 : 3 diff --git a/tests/baselines/reference/callWithSpread2.errors.txt b/tests/baselines/reference/callWithSpread2.errors.txt new file mode 100644 index 0000000000..cfea427a2a --- /dev/null +++ b/tests/baselines/reference/callWithSpread2.errors.txt @@ -0,0 +1,81 @@ +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(30,5): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(31,5): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(32,13): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(33,13): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(34,11): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(35,11): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(36,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(37,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(38,1): error TS2346: Supplied parameters do not match any signature of call target. + + +==== tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts (9 errors) ==== + declare function all(a?: number, b?: number): void; + declare function weird(a?: number | string, b?: number | string): void; + declare function prefix(s: string, a?: number, b?: number): void; + declare function rest(s: string, a?: number, b?: number, ...rest: number[]): void; + declare function normal(s: string): void; + declare function thunk(): string; + + declare var ns: number[]; + declare var mixed: (number | string)[]; + declare var tuple: [number, string]; + + // good + all(...ns) + weird(...ns) + weird(...mixed) + weird(...tuple) + prefix("a", ...ns) + rest("d", ...ns) + + + // this covers the arguments case + normal("g", ...ns) + normal("h", ...mixed) + normal("i", ...tuple) + thunk(...ns) + thunk(...mixed) + thunk(...tuple) + + // bad + all(...mixed) + ~~~~~~~~ +!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + all(...tuple) + ~~~~~~~~ +!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + prefix("b", ...mixed) + ~~~~~~~~ +!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + prefix("c", ...tuple) + ~~~~~~~~ +!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + rest("e", ...mixed) + ~~~~~~~~ +!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + rest("f", ...tuple) + ~~~~~~~~ +!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + prefix(...ns) // required parameters are required + ~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + prefix(...mixed) + ~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + prefix(...tuple) + ~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + \ No newline at end of file diff --git a/tests/baselines/reference/callWithSpread2.js b/tests/baselines/reference/callWithSpread2.js new file mode 100644 index 0000000000..55296d924f --- /dev/null +++ b/tests/baselines/reference/callWithSpread2.js @@ -0,0 +1,66 @@ +//// [callWithSpread2.ts] +declare function all(a?: number, b?: number): void; +declare function weird(a?: number | string, b?: number | string): void; +declare function prefix(s: string, a?: number, b?: number): void; +declare function rest(s: string, a?: number, b?: number, ...rest: number[]): void; +declare function normal(s: string): void; +declare function thunk(): string; + +declare var ns: number[]; +declare var mixed: (number | string)[]; +declare var tuple: [number, string]; + +// good +all(...ns) +weird(...ns) +weird(...mixed) +weird(...tuple) +prefix("a", ...ns) +rest("d", ...ns) + + +// this covers the arguments case +normal("g", ...ns) +normal("h", ...mixed) +normal("i", ...tuple) +thunk(...ns) +thunk(...mixed) +thunk(...tuple) + +// bad +all(...mixed) +all(...tuple) +prefix("b", ...mixed) +prefix("c", ...tuple) +rest("e", ...mixed) +rest("f", ...tuple) +prefix(...ns) // required parameters are required +prefix(...mixed) +prefix(...tuple) + + +//// [callWithSpread2.js] +// good +all.apply(void 0, ns); +weird.apply(void 0, ns); +weird.apply(void 0, mixed); +weird.apply(void 0, tuple); +prefix.apply(void 0, ["a"].concat(ns)); +rest.apply(void 0, ["d"].concat(ns)); +// this covers the arguments case +normal.apply(void 0, ["g"].concat(ns)); +normal.apply(void 0, ["h"].concat(mixed)); +normal.apply(void 0, ["i"].concat(tuple)); +thunk.apply(void 0, ns); +thunk.apply(void 0, mixed); +thunk.apply(void 0, tuple); +// bad +all.apply(void 0, mixed); +all.apply(void 0, tuple); +prefix.apply(void 0, ["b"].concat(mixed)); +prefix.apply(void 0, ["c"].concat(tuple)); +rest.apply(void 0, ["e"].concat(mixed)); +rest.apply(void 0, ["f"].concat(tuple)); +prefix.apply(void 0, ns); // required parameters are required +prefix.apply(void 0, mixed); +prefix.apply(void 0, tuple); diff --git a/tests/baselines/reference/computedPropertyNames47_ES5.types b/tests/baselines/reference/computedPropertyNames47_ES5.types index 19811ae8ec..137f3d63d3 100644 --- a/tests/baselines/reference/computedPropertyNames47_ES5.types +++ b/tests/baselines/reference/computedPropertyNames47_ES5.types @@ -12,7 +12,7 @@ var o = { >{ [E1.x || E2.x]: 0} : { [x: number]: number; } [E1.x || E2.x]: 0 ->E1.x || E2.x : E1 | E2 +>E1.x || E2.x : E2 >E1.x : E1 >E1 : typeof E1 >x : E1 diff --git a/tests/baselines/reference/computedPropertyNames47_ES6.types b/tests/baselines/reference/computedPropertyNames47_ES6.types index 46edecb450..04c18df83a 100644 --- a/tests/baselines/reference/computedPropertyNames47_ES6.types +++ b/tests/baselines/reference/computedPropertyNames47_ES6.types @@ -12,7 +12,7 @@ var o = { >{ [E1.x || E2.x]: 0} : { [x: number]: number; } [E1.x || E2.x]: 0 ->E1.x || E2.x : E1 | E2 +>E1.x || E2.x : E2 >E1.x : E1 >E1 : typeof E1 >x : E1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js index 5f1b97b208..d91571f93a 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js @@ -128,8 +128,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -169,8 +169,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; class C5 { f() { diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js index 1fa1b19e36..cfd7c9725e 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js @@ -264,8 +264,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -354,8 +354,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js index 98e8291ac6..4ca8322da9 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js @@ -91,8 +91,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -130,8 +130,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; function f5() { return __asyncGenerator(this, arguments, function* f5_1() { diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js index f842a2c813..410a25d2e1 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js @@ -218,8 +218,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -303,8 +303,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js index d491c0465f..602fd47d38 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js @@ -91,8 +91,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -130,8 +130,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; const f5 = function () { return __asyncGenerator(this, arguments, function* () { diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js index 779d9c5340..45d17737ce 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js @@ -218,8 +218,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -303,8 +303,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js index 22ffff01ee..760931a434 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js @@ -111,8 +111,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -152,8 +152,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; const o5 = { f() { diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js index 46f3a1efac..b5069bcea2 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js @@ -238,8 +238,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); @@ -325,8 +325,8 @@ var __asyncValues = (this && this.__asyncIterator) || function (o) { }; var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { var i, p; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : v; }; } + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt index 558540c32c..a458733bcc 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -1,15 +1,19 @@ -tests/cases/compiler/enumAssignmentCompat3.ts(68,1): error TS2324: Property 'd' is missing in type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(68,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. + Property 'd' is missing in type 'First.E'. tests/cases/compiler/enumAssignmentCompat3.ts(70,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. tests/cases/compiler/enumAssignmentCompat3.ts(71,1): error TS2322: Type 'Nope' is not assignable to type 'E'. tests/cases/compiler/enumAssignmentCompat3.ts(72,1): error TS2322: Type 'Decl.E' is not assignable to type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(75,1): error TS2324: Property 'c' is missing in type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(75,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. + Property 'c' is missing in type 'Ab.E'. tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. + Property 'a' is missing in type 'Cd.E'. tests/cases/compiler/enumAssignmentCompat3.ts(77,1): error TS2322: Type 'E' is not assignable to type 'Nope'. tests/cases/compiler/enumAssignmentCompat3.ts(78,1): error TS2322: Type 'First.E' is not assignable to type 'Decl.E'. tests/cases/compiler/enumAssignmentCompat3.ts(82,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. tests/cases/compiler/enumAssignmentCompat3.ts(83,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2324: Property 'd' is missing in type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. + Property 'd' is missing in type 'First.E'. ==== tests/cases/compiler/enumAssignmentCompat3.ts (11 errors) ==== @@ -82,7 +86,8 @@ tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2324: Property 'd' abc = secondAbc; // ok abc = secondAbcd; // missing 'd' ~~~ -!!! error TS2324: Property 'd' is missing in type 'First.E'. +!!! error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +!!! error TS2322: Property 'd' is missing in type 'First.E'. abc = secondAb; // ok abc = secondCd; // missing 'd' ~~~ @@ -98,10 +103,12 @@ tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2324: Property 'd' secondAbcd = abc; // ok secondAb = abc; // missing 'c' ~~~~~~~~ -!!! error TS2324: Property 'c' is missing in type 'Ab.E'. +!!! error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +!!! error TS2322: Property 'c' is missing in type 'Ab.E'. secondCd = abc; // missing 'a' and 'b' ~~~~~~~~ !!! error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +!!! error TS2322: Property 'a' is missing in type 'Cd.E'. nope = abc; // nope! ~~~~ !!! error TS2322: Type 'E' is not assignable to type 'Nope'. @@ -121,7 +128,8 @@ tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2324: Property 'd' // merged enums compare all their members abc = merged; // missing 'd' ~~~ -!!! error TS2324: Property 'd' is missing in type 'First.E'. +!!! error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. +!!! error TS2322: Property 'd' is missing in type 'First.E'. merged = abc; // ok abc = merged2; // ok merged2 = abc; // ok \ No newline at end of file diff --git a/tests/baselines/reference/enumBasics.errors.txt b/tests/baselines/reference/enumBasics.errors.txt deleted file mode 100644 index 4d82402b8e..0000000000 --- a/tests/baselines/reference/enumBasics.errors.txt +++ /dev/null @@ -1,86 +0,0 @@ -tests/cases/conformance/enums/enumBasics.ts(13,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'e' must be of type 'typeof E1', but here has type '{ readonly [n: number]: string; readonly A: E1; readonly B: E1; readonly C: E1; }'. - - -==== tests/cases/conformance/enums/enumBasics.ts (1 errors) ==== - // Enum without initializers have first member = 0 and successive members = N + 1 - enum E1 { - A, - B, - C - } - - // Enum type is a subtype of Number - var x: number = E1.A; - - // Enum object type is anonymous with properties of the enum type and numeric indexer - var e = E1; - var e: { - ~ -!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'e' must be of type 'typeof E1', but here has type '{ readonly [n: number]: string; readonly A: E1; readonly B: E1; readonly C: E1; }'. - readonly A: E1; - readonly B: E1; - readonly C: E1; - readonly [n: number]: string; - }; - var e: typeof E1; - - // Reverse mapping of enum returns string name of property - var s = E1[e.A]; - var s: string; - - - // Enum with only constant members - enum E2 { - A = 1, B = 2, C = 3 - } - - // Enum with only computed members - enum E3 { - X = 'foo'.length, Y = 4 + 3, Z = +'foo' - } - - // Enum with constant members followed by computed members - enum E4 { - X = 0, Y, Z = 'foo'.length - } - - // Enum with > 2 constant members with no initializer for first member, non zero initializer for second element - enum E5 { - A, - B = 3, - C // 4 - } - - enum E6 { - A, - B = 0, - C // 1 - } - - // Enum with computed member initializer of type 'any' - enum E7 { - A = 'foo'['foo'] - } - - // Enum with computed member initializer of type number - enum E8 { - B = 'foo'['foo'] - } - - //Enum with computed member intializer of same enum type - enum E9 { - A, - B = A - } - - // (refer to .js to validate) - // Enum constant members are propagated - var doNotPropagate = [ - E8.B, E7.A, E4.Z, E3.X, E3.Y, E3.Z - ]; - // Enum computed members are not propagated - var doPropagate = [ - E9.A, E9.B, E6.B, E6.C, E6.A, E5.A, E5.B, E5.C - ]; - - \ No newline at end of file diff --git a/tests/baselines/reference/enumBasics.js b/tests/baselines/reference/enumBasics.js index 4ac41c0f3d..3db9bc566c 100644 --- a/tests/baselines/reference/enumBasics.js +++ b/tests/baselines/reference/enumBasics.js @@ -12,9 +12,9 @@ var x: number = E1.A; // Enum object type is anonymous with properties of the enum type and numeric indexer var e = E1; var e: { - readonly A: E1; - readonly B: E1; - readonly C: E1; + readonly A: E1.A; + readonly B: E1.B; + readonly C: E1.C; readonly [n: number]: string; }; var e: typeof E1; diff --git a/tests/baselines/reference/enumBasics.symbols b/tests/baselines/reference/enumBasics.symbols index ce81a80ca5..948c171183 100644 --- a/tests/baselines/reference/enumBasics.symbols +++ b/tests/baselines/reference/enumBasics.symbols @@ -28,17 +28,20 @@ var e = E1; var e: { >e : Symbol(e, Decl(enumBasics.ts, 11, 3), Decl(enumBasics.ts, 12, 3), Decl(enumBasics.ts, 18, 3)) - readonly A: E1; + readonly A: E1.A; >A : Symbol(A, Decl(enumBasics.ts, 12, 8)) >E1 : Symbol(E1, Decl(enumBasics.ts, 0, 0)) +>A : Symbol(E1.A, Decl(enumBasics.ts, 1, 9)) - readonly B: E1; ->B : Symbol(B, Decl(enumBasics.ts, 13, 19)) + readonly B: E1.B; +>B : Symbol(B, Decl(enumBasics.ts, 13, 21)) >E1 : Symbol(E1, Decl(enumBasics.ts, 0, 0)) +>B : Symbol(E1.B, Decl(enumBasics.ts, 2, 6)) - readonly C: E1; ->C : Symbol(C, Decl(enumBasics.ts, 14, 19)) + readonly C: E1.C; +>C : Symbol(C, Decl(enumBasics.ts, 14, 21)) >E1 : Symbol(E1, Decl(enumBasics.ts, 0, 0)) +>C : Symbol(E1.C, Decl(enumBasics.ts, 3, 6)) readonly [n: number]: string; >n : Symbol(n, Decl(enumBasics.ts, 16, 14)) diff --git a/tests/baselines/reference/enumBasics.types b/tests/baselines/reference/enumBasics.types index 9e68b06bc3..c2e1ac94fd 100644 --- a/tests/baselines/reference/enumBasics.types +++ b/tests/baselines/reference/enumBasics.types @@ -4,21 +4,21 @@ enum E1 { >E1 : E1 A, ->A : E1 +>A : E1.A B, ->B : E1 +>B : E1.B C ->C : E1 +>C : E1.C } // Enum type is a subtype of Number var x: number = E1.A; >x : number ->E1.A : E1 +>E1.A : E1.A >E1 : typeof E1 ->A : E1 +>A : E1.A // Enum object type is anonymous with properties of the enum type and numeric indexer var e = E1; @@ -28,17 +28,20 @@ var e = E1; var e: { >e : typeof E1 - readonly A: E1; ->A : E1 ->E1 : E1 + readonly A: E1.A; +>A : E1.A +>E1 : any +>A : E1.A - readonly B: E1; ->B : E1 ->E1 : E1 + readonly B: E1.B; +>B : E1.B +>E1 : any +>B : E1.B - readonly C: E1; ->C : E1 ->E1 : E1 + readonly C: E1.C; +>C : E1.C +>E1 : any +>C : E1.C readonly [n: number]: string; >n : number @@ -53,9 +56,9 @@ var s = E1[e.A]; >s : string >E1[e.A] : string >E1 : typeof E1 ->e.A : E1 +>e.A : E1.A >e : typeof E1 ->A : E1 +>A : E1.A var s: string; >s : string @@ -66,12 +69,12 @@ enum E2 { >E2 : E2 A = 1, B = 2, C = 3 ->A : E2 ->1 : number ->B : E2 ->2 : number ->C : E2 ->3 : number +>A : E2.A +>1 : 1 +>B : E2.B +>2 : 2 +>C : E2.C +>3 : 3 } // Enum with only computed members @@ -81,15 +84,15 @@ enum E3 { X = 'foo'.length, Y = 4 + 3, Z = +'foo' >X : E3 >'foo'.length : number ->'foo' : string +>'foo' : "foo" >length : number >Y : E3 >4 + 3 : number ->4 : number ->3 : number +>4 : 4 +>3 : 3 >Z : E3 >+'foo' : number ->'foo' : string +>'foo' : "foo" } // Enum with constant members followed by computed members @@ -98,11 +101,11 @@ enum E4 { X = 0, Y, Z = 'foo'.length >X : E4 ->0 : number +>0 : 0 >Y : E4 >Z : E4 >'foo'.length : number ->'foo' : string +>'foo' : "foo" >length : number } @@ -111,28 +114,28 @@ enum E5 { >E5 : E5 A, ->A : E5 +>A : E5.A B = 3, ->B : E5 ->3 : number +>B : E5.B +>3 : 3 C // 4 ->C : E5 +>C : E5.C } enum E6 { >E6 : E6 A, ->A : E6 +>A : E6.A B = 0, ->B : E6 ->0 : number +>B : E6.A +>0 : 0 C // 1 ->C : E6 +>C : E6.C } // Enum with computed member initializer of type 'any' @@ -142,8 +145,8 @@ enum E7 { A = 'foo'['foo'] >A : E7 >'foo'['foo'] : any ->'foo' : string ->'foo' : string +>'foo' : "foo" +>'foo' : "foo" } // Enum with computed member initializer of type number @@ -153,8 +156,8 @@ enum E8 { B = 'foo'['foo'] >B : E8 >'foo'['foo'] : any ->'foo' : string ->'foo' : string +>'foo' : "foo" +>'foo' : "foo" } //Enum with computed member intializer of same enum type @@ -198,8 +201,8 @@ var doNotPropagate = [ ]; // Enum computed members are not propagated var doPropagate = [ ->doPropagate : (E5 | E6 | E9)[] ->[ E9.A, E9.B, E6.B, E6.C, E6.A, E5.A, E5.B, E5.C] : (E5 | E6 | E9)[] +>doPropagate : (E9 | E6 | E5)[] +>[ E9.A, E9.B, E6.B, E6.C, E6.A, E5.A, E5.B, E5.C] : (E9 | E6 | E5)[] E9.A, E9.B, E6.B, E6.C, E6.A, E5.A, E5.B, E5.C >E9.A : E9 @@ -208,24 +211,24 @@ var doPropagate = [ >E9.B : E9 >E9 : typeof E9 >B : E9 ->E6.B : E6 +>E6.B : E6.A >E6 : typeof E6 ->B : E6 ->E6.C : E6 +>B : E6.A +>E6.C : E6.C >E6 : typeof E6 ->C : E6 ->E6.A : E6 +>C : E6.C +>E6.A : E6.A >E6 : typeof E6 ->A : E6 ->E5.A : E5 +>A : E6.A +>E5.A : E5.A >E5 : typeof E5 ->A : E5 ->E5.B : E5 +>A : E5.A +>E5.B : E5.B >E5 : typeof E5 ->B : E5 ->E5.C : E5 +>B : E5.B +>E5.C : E5.C >E5 : typeof E5 ->C : E5 +>C : E5.C ]; diff --git a/tests/baselines/reference/enumClassification.js b/tests/baselines/reference/enumClassification.js new file mode 100644 index 0000000000..0a046dc60d --- /dev/null +++ b/tests/baselines/reference/enumClassification.js @@ -0,0 +1,218 @@ +//// [enumClassification.ts] +// An enum type where each member has no initializer or an initializer that specififes +// a numeric literal, a string literal, or a single identifier naming another member in +// the enum type is classified as a literal enum type. An enum type that doesn't adhere +// to this pattern is classified as a numeric enum type. + +// Examples of literal enum types + +enum E01 { + A +} + +enum E02 { + A = 123 +} + +enum E03 { + A = "hello" +} + +enum E04 { + A, + B, + C +} + +enum E05 { + A, + B = 10, + C +} + +enum E06 { + A = "one", + B = "two", + C = "three" +} + +enum E07 { + A, + B, + C = "hi", + D = 10, + E, + F = "bye" +} + +enum E08 { + A = 10, + B = "hello", + C = A, + D = B, + E = C, +} + +// Examples of numeric enum types with only constant members + +enum E10 {} + +enum E11 { + A = +0, + B, + C +} + +enum E12 { + A = 1 << 0, + B = 1 << 1, + C = 1 << 2 +} + +// Examples of numeric enum types with constant and computed members + +enum E20 { + A = "foo".length, + B = A + 1, + C = +"123", + D = Math.sin(1) +} + + +//// [enumClassification.js] +// An enum type where each member has no initializer or an initializer that specififes +// a numeric literal, a string literal, or a single identifier naming another member in +// the enum type is classified as a literal enum type. An enum type that doesn't adhere +// to this pattern is classified as a numeric enum type. +// Examples of literal enum types +var E01; +(function (E01) { + E01[E01["A"] = 0] = "A"; +})(E01 || (E01 = {})); +var E02; +(function (E02) { + E02[E02["A"] = 123] = "A"; +})(E02 || (E02 = {})); +var E03; +(function (E03) { + E03["A"] = "hello"; +})(E03 || (E03 = {})); +var E04; +(function (E04) { + E04[E04["A"] = 0] = "A"; + E04[E04["B"] = 1] = "B"; + E04[E04["C"] = 2] = "C"; +})(E04 || (E04 = {})); +var E05; +(function (E05) { + E05[E05["A"] = 0] = "A"; + E05[E05["B"] = 10] = "B"; + E05[E05["C"] = 11] = "C"; +})(E05 || (E05 = {})); +var E06; +(function (E06) { + E06["A"] = "one"; + E06["B"] = "two"; + E06["C"] = "three"; +})(E06 || (E06 = {})); +var E07; +(function (E07) { + E07[E07["A"] = 0] = "A"; + E07[E07["B"] = 1] = "B"; + E07["C"] = "hi"; + E07[E07["D"] = 10] = "D"; + E07[E07["E"] = 11] = "E"; + E07["F"] = "bye"; +})(E07 || (E07 = {})); +var E08; +(function (E08) { + E08[E08["A"] = 10] = "A"; + E08["B"] = "hello"; + E08[E08["C"] = 10] = "C"; + E08["D"] = "hello"; + E08[E08["E"] = 10] = "E"; +})(E08 || (E08 = {})); +// Examples of numeric enum types with only constant members +var E10; +(function (E10) { +})(E10 || (E10 = {})); +var E11; +(function (E11) { + E11[E11["A"] = 0] = "A"; + E11[E11["B"] = 1] = "B"; + E11[E11["C"] = 2] = "C"; +})(E11 || (E11 = {})); +var E12; +(function (E12) { + E12[E12["A"] = 1] = "A"; + E12[E12["B"] = 2] = "B"; + E12[E12["C"] = 4] = "C"; +})(E12 || (E12 = {})); +// Examples of numeric enum types with constant and computed members +var E20; +(function (E20) { + E20[E20["A"] = "foo".length] = "A"; + E20[E20["B"] = E20.A + 1] = "B"; + E20[E20["C"] = +"123"] = "C"; + E20[E20["D"] = Math.sin(1)] = "D"; +})(E20 || (E20 = {})); + + +//// [enumClassification.d.ts] +declare enum E01 { + A = 0, +} +declare enum E02 { + A = 123, +} +declare enum E03 { + A = "hello", +} +declare enum E04 { + A = 0, + B = 1, + C = 2, +} +declare enum E05 { + A = 0, + B = 10, + C = 11, +} +declare enum E06 { + A = "one", + B = "two", + C = "three", +} +declare enum E07 { + A = 0, + B = 1, + C = "hi", + D = 10, + E = 11, + F = "bye", +} +declare enum E08 { + A = 10, + B = "hello", + C = 10, + D = "hello", + E = 10, +} +declare enum E10 { +} +declare enum E11 { + A = 0, + B = 1, + C = 2, +} +declare enum E12 { + A = 1, + B = 2, + C = 4, +} +declare enum E20 { + A, + B, + C, + D, +} diff --git a/tests/baselines/reference/enumClassification.symbols b/tests/baselines/reference/enumClassification.symbols new file mode 100644 index 0000000000..119162e26a --- /dev/null +++ b/tests/baselines/reference/enumClassification.symbols @@ -0,0 +1,167 @@ +=== tests/cases/conformance/enums/enumClassification.ts === +// An enum type where each member has no initializer or an initializer that specififes +// a numeric literal, a string literal, or a single identifier naming another member in +// the enum type is classified as a literal enum type. An enum type that doesn't adhere +// to this pattern is classified as a numeric enum type. + +// Examples of literal enum types + +enum E01 { +>E01 : Symbol(E01, Decl(enumClassification.ts, 0, 0)) + + A +>A : Symbol(E01.A, Decl(enumClassification.ts, 7, 10)) +} + +enum E02 { +>E02 : Symbol(E02, Decl(enumClassification.ts, 9, 1)) + + A = 123 +>A : Symbol(E02.A, Decl(enumClassification.ts, 11, 10)) +} + +enum E03 { +>E03 : Symbol(E03, Decl(enumClassification.ts, 13, 1)) + + A = "hello" +>A : Symbol(E03.A, Decl(enumClassification.ts, 15, 10)) +} + +enum E04 { +>E04 : Symbol(E04, Decl(enumClassification.ts, 17, 1)) + + A, +>A : Symbol(E04.A, Decl(enumClassification.ts, 19, 10)) + + B, +>B : Symbol(E04.B, Decl(enumClassification.ts, 20, 6)) + + C +>C : Symbol(E04.C, Decl(enumClassification.ts, 21, 6)) +} + +enum E05 { +>E05 : Symbol(E05, Decl(enumClassification.ts, 23, 1)) + + A, +>A : Symbol(E05.A, Decl(enumClassification.ts, 25, 10)) + + B = 10, +>B : Symbol(E05.B, Decl(enumClassification.ts, 26, 6)) + + C +>C : Symbol(E05.C, Decl(enumClassification.ts, 27, 11)) +} + +enum E06 { +>E06 : Symbol(E06, Decl(enumClassification.ts, 29, 1)) + + A = "one", +>A : Symbol(E06.A, Decl(enumClassification.ts, 31, 10)) + + B = "two", +>B : Symbol(E06.B, Decl(enumClassification.ts, 32, 14)) + + C = "three" +>C : Symbol(E06.C, Decl(enumClassification.ts, 33, 14)) +} + +enum E07 { +>E07 : Symbol(E07, Decl(enumClassification.ts, 35, 1)) + + A, +>A : Symbol(E07.A, Decl(enumClassification.ts, 37, 10)) + + B, +>B : Symbol(E07.B, Decl(enumClassification.ts, 38, 6)) + + C = "hi", +>C : Symbol(E07.C, Decl(enumClassification.ts, 39, 6)) + + D = 10, +>D : Symbol(E07.D, Decl(enumClassification.ts, 40, 13)) + + E, +>E : Symbol(E07.E, Decl(enumClassification.ts, 41, 11)) + + F = "bye" +>F : Symbol(E07.F, Decl(enumClassification.ts, 42, 6)) +} + +enum E08 { +>E08 : Symbol(E08, Decl(enumClassification.ts, 44, 1)) + + A = 10, +>A : Symbol(E08.A, Decl(enumClassification.ts, 46, 10)) + + B = "hello", +>B : Symbol(E08.B, Decl(enumClassification.ts, 47, 11)) + + C = A, +>C : Symbol(E08.C, Decl(enumClassification.ts, 48, 16)) +>A : Symbol(E08.A, Decl(enumClassification.ts, 46, 10)) + + D = B, +>D : Symbol(E08.D, Decl(enumClassification.ts, 49, 10)) +>B : Symbol(E08.B, Decl(enumClassification.ts, 47, 11)) + + E = C, +>E : Symbol(E08.E, Decl(enumClassification.ts, 50, 10)) +>C : Symbol(E08.C, Decl(enumClassification.ts, 48, 16)) +} + +// Examples of numeric enum types with only constant members + +enum E10 {} +>E10 : Symbol(E10, Decl(enumClassification.ts, 52, 1)) + +enum E11 { +>E11 : Symbol(E11, Decl(enumClassification.ts, 56, 11)) + + A = +0, +>A : Symbol(E11.A, Decl(enumClassification.ts, 58, 10)) + + B, +>B : Symbol(E11.B, Decl(enumClassification.ts, 59, 11)) + + C +>C : Symbol(E11.C, Decl(enumClassification.ts, 60, 6)) +} + +enum E12 { +>E12 : Symbol(E12, Decl(enumClassification.ts, 62, 1)) + + A = 1 << 0, +>A : Symbol(E12.A, Decl(enumClassification.ts, 64, 10)) + + B = 1 << 1, +>B : Symbol(E12.B, Decl(enumClassification.ts, 65, 15)) + + C = 1 << 2 +>C : Symbol(E12.C, Decl(enumClassification.ts, 66, 15)) +} + +// Examples of numeric enum types with constant and computed members + +enum E20 { +>E20 : Symbol(E20, Decl(enumClassification.ts, 68, 1)) + + A = "foo".length, +>A : Symbol(E20.A, Decl(enumClassification.ts, 72, 10)) +>"foo".length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + + B = A + 1, +>B : Symbol(E20.B, Decl(enumClassification.ts, 73, 21)) +>A : Symbol(E20.A, Decl(enumClassification.ts, 72, 10)) + + C = +"123", +>C : Symbol(E20.C, Decl(enumClassification.ts, 74, 14)) + + D = Math.sin(1) +>D : Symbol(E20.D, Decl(enumClassification.ts, 75, 15)) +>Math.sin : Symbol(Math.sin, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>sin : Symbol(Math.sin, Decl(lib.d.ts, --, --)) +} + diff --git a/tests/baselines/reference/enumClassification.types b/tests/baselines/reference/enumClassification.types new file mode 100644 index 0000000000..d0581c7fca --- /dev/null +++ b/tests/baselines/reference/enumClassification.types @@ -0,0 +1,196 @@ +=== tests/cases/conformance/enums/enumClassification.ts === +// An enum type where each member has no initializer or an initializer that specififes +// a numeric literal, a string literal, or a single identifier naming another member in +// the enum type is classified as a literal enum type. An enum type that doesn't adhere +// to this pattern is classified as a numeric enum type. + +// Examples of literal enum types + +enum E01 { +>E01 : E01 + + A +>A : E01 +} + +enum E02 { +>E02 : E02 + + A = 123 +>A : E02 +>123 : 123 +} + +enum E03 { +>E03 : E03 + + A = "hello" +>A : E03 +>"hello" : "hello" +} + +enum E04 { +>E04 : E04 + + A, +>A : E04.A + + B, +>B : E04.B + + C +>C : E04.C +} + +enum E05 { +>E05 : E05 + + A, +>A : E05.A + + B = 10, +>B : E05.B +>10 : 10 + + C +>C : E05.C +} + +enum E06 { +>E06 : E06 + + A = "one", +>A : E06.A +>"one" : "one" + + B = "two", +>B : E06.B +>"two" : "two" + + C = "three" +>C : E06.C +>"three" : "three" +} + +enum E07 { +>E07 : E07 + + A, +>A : E07.A + + B, +>B : E07.B + + C = "hi", +>C : E07.C +>"hi" : "hi" + + D = 10, +>D : E07.D +>10 : 10 + + E, +>E : E07.E + + F = "bye" +>F : E07.F +>"bye" : "bye" +} + +enum E08 { +>E08 : E08 + + A = 10, +>A : E08.A +>10 : 10 + + B = "hello", +>B : E08.B +>"hello" : "hello" + + C = A, +>C : E08.A +>A : E08.A + + D = B, +>D : E08.B +>B : E08.B + + E = C, +>E : E08.A +>C : E08.A +} + +// Examples of numeric enum types with only constant members + +enum E10 {} +>E10 : E10 + +enum E11 { +>E11 : E11 + + A = +0, +>A : E11 +>+0 : number +>0 : 0 + + B, +>B : E11 + + C +>C : E11 +} + +enum E12 { +>E12 : E12 + + A = 1 << 0, +>A : E12 +>1 << 0 : number +>1 : 1 +>0 : 0 + + B = 1 << 1, +>B : E12 +>1 << 1 : number +>1 : 1 +>1 : 1 + + C = 1 << 2 +>C : E12 +>1 << 2 : number +>1 : 1 +>2 : 2 +} + +// Examples of numeric enum types with constant and computed members + +enum E20 { +>E20 : E20 + + A = "foo".length, +>A : E20 +>"foo".length : number +>"foo" : "foo" +>length : number + + B = A + 1, +>B : E20 +>A + 1 : number +>A : E20 +>1 : 1 + + C = +"123", +>C : E20 +>+"123" : number +>"123" : "123" + + D = Math.sin(1) +>D : E20 +>Math.sin(1) : number +>Math.sin : (x: number) => number +>Math : Math +>sin : (x: number) => number +>1 : 1 +} + diff --git a/tests/baselines/reference/enumErrors.errors.txt b/tests/baselines/reference/enumErrors.errors.txt index 3efa042ff3..af719d47ae 100644 --- a/tests/baselines/reference/enumErrors.errors.txt +++ b/tests/baselines/reference/enumErrors.errors.txt @@ -3,13 +3,17 @@ tests/cases/conformance/enums/enumErrors.ts(3,6): error TS2431: Enum name cannot tests/cases/conformance/enums/enumErrors.ts(4,6): error TS2431: Enum name cannot be 'string'. tests/cases/conformance/enums/enumErrors.ts(5,6): error TS2431: Enum name cannot be 'boolean'. tests/cases/conformance/enums/enumErrors.ts(9,9): error TS2322: Type 'Number' is not assignable to type 'E5'. -tests/cases/conformance/enums/enumErrors.ts(26,9): error TS2322: Type '""' is not assignable to type 'E11'. +tests/cases/conformance/enums/enumErrors.ts(26,9): error TS2322: Type 'true' is not assignable to type 'E11'. tests/cases/conformance/enums/enumErrors.ts(27,9): error TS2322: Type 'Date' is not assignable to type 'E11'. tests/cases/conformance/enums/enumErrors.ts(28,9): error TS2304: Cannot find name 'window'. tests/cases/conformance/enums/enumErrors.ts(29,9): error TS2322: Type '{}' is not assignable to type 'E11'. +tests/cases/conformance/enums/enumErrors.ts(35,9): error TS2553: Computed values are not permitted in an enum with string valued members. +tests/cases/conformance/enums/enumErrors.ts(36,9): error TS2553: Computed values are not permitted in an enum with string valued members. +tests/cases/conformance/enums/enumErrors.ts(37,9): error TS2553: Computed values are not permitted in an enum with string valued members. +tests/cases/conformance/enums/enumErrors.ts(38,9): error TS2553: Computed values are not permitted in an enum with string valued members. -==== tests/cases/conformance/enums/enumErrors.ts (9 errors) ==== +==== tests/cases/conformance/enums/enumErrors.ts (13 errors) ==== // Enum named with PredefinedTypes enum any { } ~~~ @@ -45,9 +49,9 @@ tests/cases/conformance/enums/enumErrors.ts(29,9): error TS2322: Type '{}' is no // Enum with computed member intializer of other types enum E11 { - A = '', - ~~ -!!! error TS2322: Type '""' is not assignable to type 'E11'. + A = true, + ~~~~ +!!! error TS2322: Type 'true' is not assignable to type 'E11'. B = new Date(), ~~~~~~~~~~ !!! error TS2322: Type 'Date' is not assignable to type 'E11'. @@ -58,4 +62,21 @@ tests/cases/conformance/enums/enumErrors.ts(29,9): error TS2322: Type '{}' is no ~~ !!! error TS2322: Type '{}' is not assignable to type 'E11'. } + + // Enum with string valued member and computed member initializers + enum E12 { + A = '', + B = new Date(), + ~~~~~~~~~~ +!!! error TS2553: Computed values are not permitted in an enum with string valued members. + C = window, + ~~~~~~ +!!! error TS2553: Computed values are not permitted in an enum with string valued members. + D = {}, + ~~ +!!! error TS2553: Computed values are not permitted in an enum with string valued members. + E = 1 + 1, + ~~~~~ +!!! error TS2553: Computed values are not permitted in an enum with string valued members. + } \ No newline at end of file diff --git a/tests/baselines/reference/enumErrors.js b/tests/baselines/reference/enumErrors.js index a8ecdf2470..17b67864c7 100644 --- a/tests/baselines/reference/enumErrors.js +++ b/tests/baselines/reference/enumErrors.js @@ -24,11 +24,20 @@ enum E10 { // Enum with computed member intializer of other types enum E11 { - A = '', + A = true, B = new Date(), C = window, D = {} } + +// Enum with string valued member and computed member initializers +enum E12 { + A = '', + B = new Date(), + C = window, + D = {}, + E = 1 + 1, +} //// [enumErrors.js] @@ -65,8 +74,17 @@ var E10; // Enum with computed member intializer of other types var E11; (function (E11) { - E11[E11["A"] = ''] = "A"; + E11[E11["A"] = true] = "A"; E11[E11["B"] = new Date()] = "B"; E11[E11["C"] = window] = "C"; E11[E11["D"] = {}] = "D"; })(E11 || (E11 = {})); +// Enum with string valued member and computed member initializers +var E12; +(function (E12) { + E12["A"] = ""; + E12[E12["B"] = 0] = "B"; + E12[E12["C"] = 0] = "C"; + E12[E12["D"] = 0] = "D"; + E12[E12["E"] = 0] = "E"; +})(E12 || (E12 = {})); diff --git a/tests/baselines/reference/escapedIdentifiers.types b/tests/baselines/reference/escapedIdentifiers.types index 6d48bb3392..ef6c0983d3 100644 --- a/tests/baselines/reference/escapedIdentifiers.types +++ b/tests/baselines/reference/escapedIdentifiers.types @@ -220,7 +220,7 @@ class testClass { >testClass : testClass public func(arg1: number, arg\u0032: string, arg\u0033: boolean, arg4: number) { ->func : (arg1: number, arg\u0032: string, arg\u0033: boolean, arg4: number) => void +>func : (arg1: number, arg2: string, arg3: boolean, arg4: number) => void >arg1 : number >arg\u0032 : string >arg\u0033 : boolean diff --git a/tests/baselines/reference/forwardRefInEnum.js b/tests/baselines/reference/forwardRefInEnum.js index 555454dcca..592adbd253 100644 --- a/tests/baselines/reference/forwardRefInEnum.js +++ b/tests/baselines/reference/forwardRefInEnum.js @@ -19,11 +19,11 @@ var E1; (function (E1) { // illegal case // forward reference to the element of the same enum - E1[E1["X"] = E1.Y] = "X"; - E1[E1["X1"] = E1["Y"]] = "X1"; + E1[E1["X"] = 0] = "X"; + E1[E1["X1"] = 0] = "X1"; // forward reference to the element of the same enum - E1[E1["Y"] = E1.Z] = "Y"; - E1[E1["Y1"] = E1["Z"]] = "Y1"; + E1[E1["Y"] = 0] = "Y"; + E1[E1["Y1"] = 0] = "Y1"; })(E1 || (E1 = {})); (function (E1) { E1[E1["Z"] = 4] = "Z"; diff --git a/tests/baselines/reference/literalTypes2.types b/tests/baselines/reference/literalTypes2.types index 716b016f64..ab1d3e199d 100644 --- a/tests/baselines/reference/literalTypes2.types +++ b/tests/baselines/reference/literalTypes2.types @@ -290,7 +290,7 @@ function f3() { >c2 : 1 | "two" let x3 = c3; ->x3 : number | boolean | E +>x3 : number | boolean >c3 : true | E.A | 123 let x4 = c4; diff --git a/tests/baselines/reference/logicalAndOperatorWithEveryType.types b/tests/baselines/reference/logicalAndOperatorWithEveryType.types index 54770acfab..cbe37d54a4 100644 --- a/tests/baselines/reference/logicalAndOperatorWithEveryType.types +++ b/tests/baselines/reference/logicalAndOperatorWithEveryType.types @@ -365,7 +365,7 @@ var rf5 = a5 && a6; var rf6 = a6 && a6; >rf6 : E ->a6 && a6 : E.b | E.c +>a6 && a6 : E >a6 : E >a6 : E.b | E.c diff --git a/tests/baselines/reference/logicalOrOperatorWithEveryType.types b/tests/baselines/reference/logicalOrOperatorWithEveryType.types index 327ae64cf0..5e6fa98d74 100644 --- a/tests/baselines/reference/logicalOrOperatorWithEveryType.types +++ b/tests/baselines/reference/logicalOrOperatorWithEveryType.types @@ -128,7 +128,7 @@ var rb5 = a5 || a2; // void || boolean is void | boolean var rb6 = a6 || a2; // enum || boolean is E | boolean >rb6 : boolean | E ->a6 || a2 : boolean | E +>a6 || a2 : boolean | E.b | E.c >a6 : E >a2 : boolean @@ -248,7 +248,7 @@ var rd5 = a5 || a4; // void || string is void | string var rd6 = a6 || a4; // enum || string is enum | string >rd6 : string | E ->a6 || a4 : string | E +>a6 || a4 : string | E.b | E.c >a6 : E >a4 : string @@ -308,7 +308,7 @@ var re5 = a5 || a5; // void || void is void var re6 = a6 || a5; // enum || void is enum | void >re6 : void | E ->a6 || a5 : void | E +>a6 || a5 : void | E.b | E.c >a6 : E >a5 : void @@ -428,7 +428,7 @@ var rh5 = a5 || a7; // void || object is void | object var rh6 = a6 || a7; // enum || object is enum | object >rh6 : E | { a: string; } ->a6 || a7 : E | { a: string; } +>a6 || a7 : E.b | E.c | { a: string; } >a6 : E >a7 : { a: string; } @@ -488,7 +488,7 @@ var ri5 = a5 || a8; // void || array is void | array var ri6 = a6 || a8; // enum || array is enum | array >ri6 : E | string[] ->a6 || a8 : E | string[] +>a6 || a8 : E.b | E.c | string[] >a6 : E >a8 : string[] @@ -548,7 +548,7 @@ var rj5 = a5 || null; // void || null is void var rj6 = a6 || null; // enum || null is E >rj6 : E ->a6 || null : E +>a6 || null : E.b | E.c >a6 : E >null : null @@ -608,7 +608,7 @@ var rf5 = a5 || undefined; // void || undefined is void var rf6 = a6 || undefined; // enum || undefined is E >rf6 : E ->a6 || undefined : E +>a6 || undefined : E.b | E.c >a6 : E >undefined : undefined diff --git a/tests/baselines/reference/metadataOfUnion.types b/tests/baselines/reference/metadataOfUnion.types index 08afc4e81b..542d37e208 100644 --- a/tests/baselines/reference/metadataOfUnion.types +++ b/tests/baselines/reference/metadataOfUnion.types @@ -81,6 +81,6 @@ class D { >PropDeco : (target: Object, propKey: string | symbol) => void d: E | number; ->d : number | E +>d : number >E : E } diff --git a/tests/baselines/reference/objectLiteralFreshnessWithSpread.errors.txt b/tests/baselines/reference/objectLiteralFreshnessWithSpread.errors.txt new file mode 100644 index 0000000000..ac6b56f6ce --- /dev/null +++ b/tests/baselines/reference/objectLiteralFreshnessWithSpread.errors.txt @@ -0,0 +1,11 @@ +tests/cases/compiler/objectLiteralFreshnessWithSpread.ts(2,35): error TS2322: Type '{ z: number; b: number; extra: number; a: number; }' is not assignable to type '{ a: any; b: any; }'. + Object literal may only specify known properties, and 'z' does not exist in type '{ a: any; b: any; }'. + + +==== tests/cases/compiler/objectLiteralFreshnessWithSpread.ts (1 errors) ==== + let x = { b: 1, extra: 2 } + let xx: { a, b } = { a: 1, ...x, z: 3 } // error for 'z', no error for 'extra' + ~~~~ +!!! error TS2322: Type '{ z: number; b: number; extra: number; a: number; }' is not assignable to type '{ a: any; b: any; }'. +!!! error TS2322: Object literal may only specify known properties, and 'z' does not exist in type '{ a: any; b: any; }'. + \ No newline at end of file diff --git a/tests/baselines/reference/objectLiteralFreshnessWithSpread.js b/tests/baselines/reference/objectLiteralFreshnessWithSpread.js new file mode 100644 index 0000000000..0a4222603a --- /dev/null +++ b/tests/baselines/reference/objectLiteralFreshnessWithSpread.js @@ -0,0 +1,16 @@ +//// [objectLiteralFreshnessWithSpread.ts] +let x = { b: 1, extra: 2 } +let xx: { a, b } = { a: 1, ...x, z: 3 } // error for 'z', no error for 'extra' + + +//// [objectLiteralFreshnessWithSpread.js] +var __assign = (this && this.__assign) || Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; +}; +var x = { b: 1, extra: 2 }; +var xx = __assign({ a: 1 }, x, { z: 3 }); // error for 'z', no error for 'extra' diff --git a/tests/baselines/reference/stringEnumLiteralTypes1.js b/tests/baselines/reference/stringEnumLiteralTypes1.js new file mode 100644 index 0000000000..4acf2ada1a --- /dev/null +++ b/tests/baselines/reference/stringEnumLiteralTypes1.js @@ -0,0 +1,178 @@ +//// [stringEnumLiteralTypes1.ts] +const enum Choice { Unknown = "", Yes = "yes", No = "no" }; + +type YesNo = Choice.Yes | Choice.No; +type NoYes = Choice.No | Choice.Yes; +type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; + +function f1() { + var a: YesNo; + var a: NoYes; + var a: Choice.Yes | Choice.No; + var a: Choice.No | Choice.Yes; +} + +function f2(a: YesNo, b: UnknownYesNo, c: Choice) { + b = a; + c = a; + c = b; +} + +function f3(a: Choice.Yes, b: YesNo) { + var x = a + b; + var y = a == b; + var y = a != b; + var y = a === b; + var y = a !== b; + var y = a > b; + var y = a < b; + var y = a >= b; + var y = a <= b; + var y = !b; +} + +declare function g(x: Choice.Yes): string; +declare function g(x: Choice.No): boolean; +declare function g(x: Choice): number; + +function f5(a: YesNo, b: UnknownYesNo, c: Choice) { + var z1 = g(Choice.Yes); + var z2 = g(Choice.No); + var z3 = g(a); + var z4 = g(b); + var z5 = g(c); +} + +function assertNever(x: never): never { + throw new Error("Unexpected value"); +} + +function f10(x: YesNo) { + switch (x) { + case Choice.Yes: return "true"; + case Choice.No: return "false"; + } +} + +function f11(x: YesNo) { + switch (x) { + case Choice.Yes: return "true"; + case Choice.No: return "false"; + } + return assertNever(x); +} + +function f12(x: UnknownYesNo) { + if (x) { + x; + } + else { + x; + } +} + +function f13(x: UnknownYesNo) { + if (x === Choice.Yes) { + x; + } + else { + x; + } +} + +type Item = + { kind: Choice.Yes, a: string } | + { kind: Choice.No, b: string }; + +function f20(x: Item) { + switch (x.kind) { + case Choice.Yes: return x.a; + case Choice.No: return x.b; + } +} + +function f21(x: Item) { + switch (x.kind) { + case Choice.Yes: return x.a; + case Choice.No: return x.b; + } + return assertNever(x); +} + +//// [stringEnumLiteralTypes1.js] +; +function f1() { + var a; + var a; + var a; + var a; +} +function f2(a, b, c) { + b = a; + c = a; + c = b; +} +function f3(a, b) { + var x = a + b; + var y = a == b; + var y = a != b; + var y = a === b; + var y = a !== b; + var y = a > b; + var y = a < b; + var y = a >= b; + var y = a <= b; + var y = !b; +} +function f5(a, b, c) { + var z1 = g("yes" /* Yes */); + var z2 = g("no" /* No */); + var z3 = g(a); + var z4 = g(b); + var z5 = g(c); +} +function assertNever(x) { + throw new Error("Unexpected value"); +} +function f10(x) { + switch (x) { + case "yes" /* Yes */: return "true"; + case "no" /* No */: return "false"; + } +} +function f11(x) { + switch (x) { + case "yes" /* Yes */: return "true"; + case "no" /* No */: return "false"; + } + return assertNever(x); +} +function f12(x) { + if (x) { + x; + } + else { + x; + } +} +function f13(x) { + if (x === "yes" /* Yes */) { + x; + } + else { + x; + } +} +function f20(x) { + switch (x.kind) { + case "yes" /* Yes */: return x.a; + case "no" /* No */: return x.b; + } +} +function f21(x) { + switch (x.kind) { + case "yes" /* Yes */: return x.a; + case "no" /* No */: return x.b; + } + return assertNever(x); +} diff --git a/tests/baselines/reference/stringEnumLiteralTypes1.symbols b/tests/baselines/reference/stringEnumLiteralTypes1.symbols new file mode 100644 index 0000000000..66c25aab85 --- /dev/null +++ b/tests/baselines/reference/stringEnumLiteralTypes1.symbols @@ -0,0 +1,353 @@ +=== tests/cases/conformance/types/literal/stringEnumLiteralTypes1.ts === +const enum Choice { Unknown = "", Yes = "yes", No = "no" }; +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Unknown : Symbol(Choice.Unknown, Decl(stringEnumLiteralTypes1.ts, 0, 19)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) + +type YesNo = Choice.Yes | Choice.No; +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes1.ts, 0, 59)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) + +type NoYes = Choice.No | Choice.Yes; +>NoYes : Symbol(NoYes, Decl(stringEnumLiteralTypes1.ts, 2, 36)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) + +type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; +>UnknownYesNo : Symbol(UnknownYesNo, Decl(stringEnumLiteralTypes1.ts, 3, 36)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Unknown : Symbol(Choice.Unknown, Decl(stringEnumLiteralTypes1.ts, 0, 19)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) + +function f1() { +>f1 : Symbol(f1, Decl(stringEnumLiteralTypes1.ts, 4, 60)) + + var a: YesNo; +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 7, 7), Decl(stringEnumLiteralTypes1.ts, 8, 7), Decl(stringEnumLiteralTypes1.ts, 9, 7), Decl(stringEnumLiteralTypes1.ts, 10, 7)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes1.ts, 0, 59)) + + var a: NoYes; +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 7, 7), Decl(stringEnumLiteralTypes1.ts, 8, 7), Decl(stringEnumLiteralTypes1.ts, 9, 7), Decl(stringEnumLiteralTypes1.ts, 10, 7)) +>NoYes : Symbol(NoYes, Decl(stringEnumLiteralTypes1.ts, 2, 36)) + + var a: Choice.Yes | Choice.No; +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 7, 7), Decl(stringEnumLiteralTypes1.ts, 8, 7), Decl(stringEnumLiteralTypes1.ts, 9, 7), Decl(stringEnumLiteralTypes1.ts, 10, 7)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) + + var a: Choice.No | Choice.Yes; +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 7, 7), Decl(stringEnumLiteralTypes1.ts, 8, 7), Decl(stringEnumLiteralTypes1.ts, 9, 7), Decl(stringEnumLiteralTypes1.ts, 10, 7)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +} + +function f2(a: YesNo, b: UnknownYesNo, c: Choice) { +>f2 : Symbol(f2, Decl(stringEnumLiteralTypes1.ts, 11, 1)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 13, 12)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes1.ts, 0, 59)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 13, 21)) +>UnknownYesNo : Symbol(UnknownYesNo, Decl(stringEnumLiteralTypes1.ts, 3, 36)) +>c : Symbol(c, Decl(stringEnumLiteralTypes1.ts, 13, 38)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) + + b = a; +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 13, 21)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 13, 12)) + + c = a; +>c : Symbol(c, Decl(stringEnumLiteralTypes1.ts, 13, 38)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 13, 12)) + + c = b; +>c : Symbol(c, Decl(stringEnumLiteralTypes1.ts, 13, 38)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 13, 21)) +} + +function f3(a: Choice.Yes, b: YesNo) { +>f3 : Symbol(f3, Decl(stringEnumLiteralTypes1.ts, 17, 1)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 19, 12)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes1.ts, 0, 59)) + + var x = a + b; +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 20, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) + + var y = a == b; +>y : Symbol(y, Decl(stringEnumLiteralTypes1.ts, 21, 7), Decl(stringEnumLiteralTypes1.ts, 22, 7), Decl(stringEnumLiteralTypes1.ts, 23, 7), Decl(stringEnumLiteralTypes1.ts, 24, 7), Decl(stringEnumLiteralTypes1.ts, 25, 7), Decl(stringEnumLiteralTypes1.ts, 26, 7), Decl(stringEnumLiteralTypes1.ts, 27, 7), Decl(stringEnumLiteralTypes1.ts, 28, 7), Decl(stringEnumLiteralTypes1.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) + + var y = a != b; +>y : Symbol(y, Decl(stringEnumLiteralTypes1.ts, 21, 7), Decl(stringEnumLiteralTypes1.ts, 22, 7), Decl(stringEnumLiteralTypes1.ts, 23, 7), Decl(stringEnumLiteralTypes1.ts, 24, 7), Decl(stringEnumLiteralTypes1.ts, 25, 7), Decl(stringEnumLiteralTypes1.ts, 26, 7), Decl(stringEnumLiteralTypes1.ts, 27, 7), Decl(stringEnumLiteralTypes1.ts, 28, 7), Decl(stringEnumLiteralTypes1.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) + + var y = a === b; +>y : Symbol(y, Decl(stringEnumLiteralTypes1.ts, 21, 7), Decl(stringEnumLiteralTypes1.ts, 22, 7), Decl(stringEnumLiteralTypes1.ts, 23, 7), Decl(stringEnumLiteralTypes1.ts, 24, 7), Decl(stringEnumLiteralTypes1.ts, 25, 7), Decl(stringEnumLiteralTypes1.ts, 26, 7), Decl(stringEnumLiteralTypes1.ts, 27, 7), Decl(stringEnumLiteralTypes1.ts, 28, 7), Decl(stringEnumLiteralTypes1.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) + + var y = a !== b; +>y : Symbol(y, Decl(stringEnumLiteralTypes1.ts, 21, 7), Decl(stringEnumLiteralTypes1.ts, 22, 7), Decl(stringEnumLiteralTypes1.ts, 23, 7), Decl(stringEnumLiteralTypes1.ts, 24, 7), Decl(stringEnumLiteralTypes1.ts, 25, 7), Decl(stringEnumLiteralTypes1.ts, 26, 7), Decl(stringEnumLiteralTypes1.ts, 27, 7), Decl(stringEnumLiteralTypes1.ts, 28, 7), Decl(stringEnumLiteralTypes1.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) + + var y = a > b; +>y : Symbol(y, Decl(stringEnumLiteralTypes1.ts, 21, 7), Decl(stringEnumLiteralTypes1.ts, 22, 7), Decl(stringEnumLiteralTypes1.ts, 23, 7), Decl(stringEnumLiteralTypes1.ts, 24, 7), Decl(stringEnumLiteralTypes1.ts, 25, 7), Decl(stringEnumLiteralTypes1.ts, 26, 7), Decl(stringEnumLiteralTypes1.ts, 27, 7), Decl(stringEnumLiteralTypes1.ts, 28, 7), Decl(stringEnumLiteralTypes1.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) + + var y = a < b; +>y : Symbol(y, Decl(stringEnumLiteralTypes1.ts, 21, 7), Decl(stringEnumLiteralTypes1.ts, 22, 7), Decl(stringEnumLiteralTypes1.ts, 23, 7), Decl(stringEnumLiteralTypes1.ts, 24, 7), Decl(stringEnumLiteralTypes1.ts, 25, 7), Decl(stringEnumLiteralTypes1.ts, 26, 7), Decl(stringEnumLiteralTypes1.ts, 27, 7), Decl(stringEnumLiteralTypes1.ts, 28, 7), Decl(stringEnumLiteralTypes1.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) + + var y = a >= b; +>y : Symbol(y, Decl(stringEnumLiteralTypes1.ts, 21, 7), Decl(stringEnumLiteralTypes1.ts, 22, 7), Decl(stringEnumLiteralTypes1.ts, 23, 7), Decl(stringEnumLiteralTypes1.ts, 24, 7), Decl(stringEnumLiteralTypes1.ts, 25, 7), Decl(stringEnumLiteralTypes1.ts, 26, 7), Decl(stringEnumLiteralTypes1.ts, 27, 7), Decl(stringEnumLiteralTypes1.ts, 28, 7), Decl(stringEnumLiteralTypes1.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) + + var y = a <= b; +>y : Symbol(y, Decl(stringEnumLiteralTypes1.ts, 21, 7), Decl(stringEnumLiteralTypes1.ts, 22, 7), Decl(stringEnumLiteralTypes1.ts, 23, 7), Decl(stringEnumLiteralTypes1.ts, 24, 7), Decl(stringEnumLiteralTypes1.ts, 25, 7), Decl(stringEnumLiteralTypes1.ts, 26, 7), Decl(stringEnumLiteralTypes1.ts, 27, 7), Decl(stringEnumLiteralTypes1.ts, 28, 7), Decl(stringEnumLiteralTypes1.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) + + var y = !b; +>y : Symbol(y, Decl(stringEnumLiteralTypes1.ts, 21, 7), Decl(stringEnumLiteralTypes1.ts, 22, 7), Decl(stringEnumLiteralTypes1.ts, 23, 7), Decl(stringEnumLiteralTypes1.ts, 24, 7), Decl(stringEnumLiteralTypes1.ts, 25, 7), Decl(stringEnumLiteralTypes1.ts, 26, 7), Decl(stringEnumLiteralTypes1.ts, 27, 7), Decl(stringEnumLiteralTypes1.ts, 28, 7), Decl(stringEnumLiteralTypes1.ts, 29, 7)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 19, 26)) +} + +declare function g(x: Choice.Yes): string; +>g : Symbol(g, Decl(stringEnumLiteralTypes1.ts, 30, 1), Decl(stringEnumLiteralTypes1.ts, 32, 42), Decl(stringEnumLiteralTypes1.ts, 33, 42)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 32, 19)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) + +declare function g(x: Choice.No): boolean; +>g : Symbol(g, Decl(stringEnumLiteralTypes1.ts, 30, 1), Decl(stringEnumLiteralTypes1.ts, 32, 42), Decl(stringEnumLiteralTypes1.ts, 33, 42)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 33, 19)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) + +declare function g(x: Choice): number; +>g : Symbol(g, Decl(stringEnumLiteralTypes1.ts, 30, 1), Decl(stringEnumLiteralTypes1.ts, 32, 42), Decl(stringEnumLiteralTypes1.ts, 33, 42)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 34, 19)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) + +function f5(a: YesNo, b: UnknownYesNo, c: Choice) { +>f5 : Symbol(f5, Decl(stringEnumLiteralTypes1.ts, 34, 38)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 36, 12)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes1.ts, 0, 59)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 36, 21)) +>UnknownYesNo : Symbol(UnknownYesNo, Decl(stringEnumLiteralTypes1.ts, 3, 36)) +>c : Symbol(c, Decl(stringEnumLiteralTypes1.ts, 36, 38)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) + + var z1 = g(Choice.Yes); +>z1 : Symbol(z1, Decl(stringEnumLiteralTypes1.ts, 37, 7)) +>g : Symbol(g, Decl(stringEnumLiteralTypes1.ts, 30, 1), Decl(stringEnumLiteralTypes1.ts, 32, 42), Decl(stringEnumLiteralTypes1.ts, 33, 42)) +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) + + var z2 = g(Choice.No); +>z2 : Symbol(z2, Decl(stringEnumLiteralTypes1.ts, 38, 7)) +>g : Symbol(g, Decl(stringEnumLiteralTypes1.ts, 30, 1), Decl(stringEnumLiteralTypes1.ts, 32, 42), Decl(stringEnumLiteralTypes1.ts, 33, 42)) +>Choice.No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) + + var z3 = g(a); +>z3 : Symbol(z3, Decl(stringEnumLiteralTypes1.ts, 39, 7)) +>g : Symbol(g, Decl(stringEnumLiteralTypes1.ts, 30, 1), Decl(stringEnumLiteralTypes1.ts, 32, 42), Decl(stringEnumLiteralTypes1.ts, 33, 42)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 36, 12)) + + var z4 = g(b); +>z4 : Symbol(z4, Decl(stringEnumLiteralTypes1.ts, 40, 7)) +>g : Symbol(g, Decl(stringEnumLiteralTypes1.ts, 30, 1), Decl(stringEnumLiteralTypes1.ts, 32, 42), Decl(stringEnumLiteralTypes1.ts, 33, 42)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 36, 21)) + + var z5 = g(c); +>z5 : Symbol(z5, Decl(stringEnumLiteralTypes1.ts, 41, 7)) +>g : Symbol(g, Decl(stringEnumLiteralTypes1.ts, 30, 1), Decl(stringEnumLiteralTypes1.ts, 32, 42), Decl(stringEnumLiteralTypes1.ts, 33, 42)) +>c : Symbol(c, Decl(stringEnumLiteralTypes1.ts, 36, 38)) +} + +function assertNever(x: never): never { +>assertNever : Symbol(assertNever, Decl(stringEnumLiteralTypes1.ts, 42, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 44, 21)) + + throw new Error("Unexpected value"); +>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +} + +function f10(x: YesNo) { +>f10 : Symbol(f10, Decl(stringEnumLiteralTypes1.ts, 46, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 48, 13)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes1.ts, 0, 59)) + + switch (x) { +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 48, 13)) + + case Choice.Yes: return "true"; +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) + + case Choice.No: return "false"; +>Choice.No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) + } +} + +function f11(x: YesNo) { +>f11 : Symbol(f11, Decl(stringEnumLiteralTypes1.ts, 53, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 55, 13)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes1.ts, 0, 59)) + + switch (x) { +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 55, 13)) + + case Choice.Yes: return "true"; +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) + + case Choice.No: return "false"; +>Choice.No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) + } + return assertNever(x); +>assertNever : Symbol(assertNever, Decl(stringEnumLiteralTypes1.ts, 42, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 55, 13)) +} + +function f12(x: UnknownYesNo) { +>f12 : Symbol(f12, Decl(stringEnumLiteralTypes1.ts, 61, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 63, 13)) +>UnknownYesNo : Symbol(UnknownYesNo, Decl(stringEnumLiteralTypes1.ts, 3, 36)) + + if (x) { +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 63, 13)) + + x; +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 63, 13)) + } + else { + x; +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 63, 13)) + } +} + +function f13(x: UnknownYesNo) { +>f13 : Symbol(f13, Decl(stringEnumLiteralTypes1.ts, 70, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 72, 13)) +>UnknownYesNo : Symbol(UnknownYesNo, Decl(stringEnumLiteralTypes1.ts, 3, 36)) + + if (x === Choice.Yes) { +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 72, 13)) +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) + + x; +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 72, 13)) + } + else { + x; +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 72, 13)) + } +} + +type Item = +>Item : Symbol(Item, Decl(stringEnumLiteralTypes1.ts, 79, 1)) + + { kind: Choice.Yes, a: string } | +>kind : Symbol(kind, Decl(stringEnumLiteralTypes1.ts, 82, 5)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 82, 23)) + + { kind: Choice.No, b: string }; +>kind : Symbol(kind, Decl(stringEnumLiteralTypes1.ts, 83, 5)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 83, 22)) + +function f20(x: Item) { +>f20 : Symbol(f20, Decl(stringEnumLiteralTypes1.ts, 83, 35)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 85, 13)) +>Item : Symbol(Item, Decl(stringEnumLiteralTypes1.ts, 79, 1)) + + switch (x.kind) { +>x.kind : Symbol(kind, Decl(stringEnumLiteralTypes1.ts, 82, 5), Decl(stringEnumLiteralTypes1.ts, 83, 5)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 85, 13)) +>kind : Symbol(kind, Decl(stringEnumLiteralTypes1.ts, 82, 5), Decl(stringEnumLiteralTypes1.ts, 83, 5)) + + case Choice.Yes: return x.a; +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>x.a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 82, 23)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 85, 13)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 82, 23)) + + case Choice.No: return x.b; +>Choice.No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) +>x.b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 83, 22)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 85, 13)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 83, 22)) + } +} + +function f21(x: Item) { +>f21 : Symbol(f21, Decl(stringEnumLiteralTypes1.ts, 90, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 92, 13)) +>Item : Symbol(Item, Decl(stringEnumLiteralTypes1.ts, 79, 1)) + + switch (x.kind) { +>x.kind : Symbol(kind, Decl(stringEnumLiteralTypes1.ts, 82, 5), Decl(stringEnumLiteralTypes1.ts, 83, 5)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 92, 13)) +>kind : Symbol(kind, Decl(stringEnumLiteralTypes1.ts, 82, 5), Decl(stringEnumLiteralTypes1.ts, 83, 5)) + + case Choice.Yes: return x.a; +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes1.ts, 0, 33)) +>x.a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 82, 23)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 92, 13)) +>a : Symbol(a, Decl(stringEnumLiteralTypes1.ts, 82, 23)) + + case Choice.No: return x.b; +>Choice.No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes1.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes1.ts, 0, 46)) +>x.b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 83, 22)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 92, 13)) +>b : Symbol(b, Decl(stringEnumLiteralTypes1.ts, 83, 22)) + } + return assertNever(x); +>assertNever : Symbol(assertNever, Decl(stringEnumLiteralTypes1.ts, 42, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes1.ts, 92, 13)) +} diff --git a/tests/baselines/reference/stringEnumLiteralTypes1.types b/tests/baselines/reference/stringEnumLiteralTypes1.types new file mode 100644 index 0000000000..b5d70ed501 --- /dev/null +++ b/tests/baselines/reference/stringEnumLiteralTypes1.types @@ -0,0 +1,383 @@ +=== tests/cases/conformance/types/literal/stringEnumLiteralTypes1.ts === +const enum Choice { Unknown = "", Yes = "yes", No = "no" }; +>Choice : Choice +>Unknown : Choice.Unknown +>"" : "" +>Yes : Choice.Yes +>"yes" : "yes" +>No : Choice.No +>"no" : "no" + +type YesNo = Choice.Yes | Choice.No; +>YesNo : YesNo +>Choice : any +>Yes : Choice.Yes +>Choice : any +>No : Choice.No + +type NoYes = Choice.No | Choice.Yes; +>NoYes : YesNo +>Choice : any +>No : Choice.No +>Choice : any +>Yes : Choice.Yes + +type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; +>UnknownYesNo : Choice +>Choice : any +>Unknown : Choice.Unknown +>Choice : any +>Yes : Choice.Yes +>Choice : any +>No : Choice.No + +function f1() { +>f1 : () => void + + var a: YesNo; +>a : YesNo +>YesNo : YesNo + + var a: NoYes; +>a : YesNo +>NoYes : YesNo + + var a: Choice.Yes | Choice.No; +>a : YesNo +>Choice : any +>Yes : Choice.Yes +>Choice : any +>No : Choice.No + + var a: Choice.No | Choice.Yes; +>a : YesNo +>Choice : any +>No : Choice.No +>Choice : any +>Yes : Choice.Yes +} + +function f2(a: YesNo, b: UnknownYesNo, c: Choice) { +>f2 : (a: YesNo, b: Choice, c: Choice) => void +>a : YesNo +>YesNo : YesNo +>b : Choice +>UnknownYesNo : Choice +>c : Choice +>Choice : Choice + + b = a; +>b = a : YesNo +>b : Choice +>a : YesNo + + c = a; +>c = a : YesNo +>c : Choice +>a : YesNo + + c = b; +>c = b : YesNo +>c : Choice +>b : YesNo +} + +function f3(a: Choice.Yes, b: YesNo) { +>f3 : (a: Choice.Yes, b: YesNo) => void +>a : Choice.Yes +>Choice : any +>Yes : Choice.Yes +>b : YesNo +>YesNo : YesNo + + var x = a + b; +>x : string +>a + b : string +>a : Choice.Yes +>b : YesNo + + var y = a == b; +>y : boolean +>a == b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a != b; +>y : boolean +>a != b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a === b; +>y : boolean +>a === b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a !== b; +>y : boolean +>a !== b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a > b; +>y : boolean +>a > b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a < b; +>y : boolean +>a < b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a >= b; +>y : boolean +>a >= b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a <= b; +>y : boolean +>a <= b : boolean +>a : Choice.Yes +>b : YesNo + + var y = !b; +>y : boolean +>!b : boolean +>b : YesNo +} + +declare function g(x: Choice.Yes): string; +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>x : Choice.Yes +>Choice : any +>Yes : Choice.Yes + +declare function g(x: Choice.No): boolean; +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>x : Choice.No +>Choice : any +>No : Choice.No + +declare function g(x: Choice): number; +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>x : Choice +>Choice : Choice + +function f5(a: YesNo, b: UnknownYesNo, c: Choice) { +>f5 : (a: YesNo, b: Choice, c: Choice) => void +>a : YesNo +>YesNo : YesNo +>b : Choice +>UnknownYesNo : Choice +>c : Choice +>Choice : Choice + + var z1 = g(Choice.Yes); +>z1 : string +>g(Choice.Yes) : string +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes + + var z2 = g(Choice.No); +>z2 : boolean +>g(Choice.No) : boolean +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>Choice.No : Choice.No +>Choice : typeof Choice +>No : Choice.No + + var z3 = g(a); +>z3 : number +>g(a) : number +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>a : YesNo + + var z4 = g(b); +>z4 : number +>g(b) : number +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>b : Choice + + var z5 = g(c); +>z5 : number +>g(c) : number +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>c : Choice +} + +function assertNever(x: never): never { +>assertNever : (x: never) => never +>x : never + + throw new Error("Unexpected value"); +>new Error("Unexpected value") : Error +>Error : ErrorConstructor +>"Unexpected value" : "Unexpected value" +} + +function f10(x: YesNo) { +>f10 : (x: YesNo) => "true" | "false" +>x : YesNo +>YesNo : YesNo + + switch (x) { +>x : YesNo + + case Choice.Yes: return "true"; +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes +>"true" : "true" + + case Choice.No: return "false"; +>Choice.No : Choice.No +>Choice : typeof Choice +>No : Choice.No +>"false" : "false" + } +} + +function f11(x: YesNo) { +>f11 : (x: YesNo) => "true" | "false" +>x : YesNo +>YesNo : YesNo + + switch (x) { +>x : YesNo + + case Choice.Yes: return "true"; +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes +>"true" : "true" + + case Choice.No: return "false"; +>Choice.No : Choice.No +>Choice : typeof Choice +>No : Choice.No +>"false" : "false" + } + return assertNever(x); +>assertNever(x) : never +>assertNever : (x: never) => never +>x : never +} + +function f12(x: UnknownYesNo) { +>f12 : (x: Choice) => void +>x : Choice +>UnknownYesNo : Choice + + if (x) { +>x : Choice + + x; +>x : YesNo + } + else { + x; +>x : Choice + } +} + +function f13(x: UnknownYesNo) { +>f13 : (x: Choice) => void +>x : Choice +>UnknownYesNo : Choice + + if (x === Choice.Yes) { +>x === Choice.Yes : boolean +>x : Choice +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes + + x; +>x : Choice.Yes + } + else { + x; +>x : Choice.Unknown | Choice.No + } +} + +type Item = +>Item : Item + + { kind: Choice.Yes, a: string } | +>kind : Choice.Yes +>Choice : any +>Yes : Choice.Yes +>a : string + + { kind: Choice.No, b: string }; +>kind : Choice.No +>Choice : any +>No : Choice.No +>b : string + +function f20(x: Item) { +>f20 : (x: Item) => string +>x : Item +>Item : Item + + switch (x.kind) { +>x.kind : YesNo +>x : Item +>kind : YesNo + + case Choice.Yes: return x.a; +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes +>x.a : string +>x : { kind: Choice.Yes; a: string; } +>a : string + + case Choice.No: return x.b; +>Choice.No : Choice.No +>Choice : typeof Choice +>No : Choice.No +>x.b : string +>x : { kind: Choice.No; b: string; } +>b : string + } +} + +function f21(x: Item) { +>f21 : (x: Item) => string +>x : Item +>Item : Item + + switch (x.kind) { +>x.kind : YesNo +>x : Item +>kind : YesNo + + case Choice.Yes: return x.a; +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes +>x.a : string +>x : { kind: Choice.Yes; a: string; } +>a : string + + case Choice.No: return x.b; +>Choice.No : Choice.No +>Choice : typeof Choice +>No : Choice.No +>x.b : string +>x : { kind: Choice.No; b: string; } +>b : string + } + return assertNever(x); +>assertNever(x) : never +>assertNever : (x: never) => never +>x : never +} diff --git a/tests/baselines/reference/stringEnumLiteralTypes2.js b/tests/baselines/reference/stringEnumLiteralTypes2.js new file mode 100644 index 0000000000..07a5de7a85 --- /dev/null +++ b/tests/baselines/reference/stringEnumLiteralTypes2.js @@ -0,0 +1,178 @@ +//// [stringEnumLiteralTypes2.ts] +const enum Choice { Unknown = "", Yes = "yes", No = "no" }; + +type YesNo = Choice.Yes | Choice.No; +type NoYes = Choice.No | Choice.Yes; +type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; + +function f1() { + var a: YesNo; + var a: NoYes; + var a: Choice.Yes | Choice.No; + var a: Choice.No | Choice.Yes; +} + +function f2(a: YesNo, b: UnknownYesNo, c: Choice) { + b = a; + c = a; + c = b; +} + +function f3(a: Choice.Yes, b: YesNo) { + var x = a + b; + var y = a == b; + var y = a != b; + var y = a === b; + var y = a !== b; + var y = a > b; + var y = a < b; + var y = a >= b; + var y = a <= b; + var y = !b; +} + +declare function g(x: Choice.Yes): string; +declare function g(x: Choice.No): boolean; +declare function g(x: Choice): number; + +function f5(a: YesNo, b: UnknownYesNo, c: Choice) { + var z1 = g(Choice.Yes); + var z2 = g(Choice.No); + var z3 = g(a); + var z4 = g(b); + var z5 = g(c); +} + +function assertNever(x: never): never { + throw new Error("Unexpected value"); +} + +function f10(x: YesNo) { + switch (x) { + case Choice.Yes: return "true"; + case Choice.No: return "false"; + } +} + +function f11(x: YesNo) { + switch (x) { + case Choice.Yes: return "true"; + case Choice.No: return "false"; + } + return assertNever(x); +} + +function f12(x: UnknownYesNo) { + if (x) { + x; + } + else { + x; + } +} + +function f13(x: UnknownYesNo) { + if (x === Choice.Yes) { + x; + } + else { + x; + } +} + +type Item = + { kind: Choice.Yes, a: string } | + { kind: Choice.No, b: string }; + +function f20(x: Item) { + switch (x.kind) { + case Choice.Yes: return x.a; + case Choice.No: return x.b; + } +} + +function f21(x: Item) { + switch (x.kind) { + case Choice.Yes: return x.a; + case Choice.No: return x.b; + } + return assertNever(x); +} + +//// [stringEnumLiteralTypes2.js] +; +function f1() { + var a; + var a; + var a; + var a; +} +function f2(a, b, c) { + b = a; + c = a; + c = b; +} +function f3(a, b) { + var x = a + b; + var y = a == b; + var y = a != b; + var y = a === b; + var y = a !== b; + var y = a > b; + var y = a < b; + var y = a >= b; + var y = a <= b; + var y = !b; +} +function f5(a, b, c) { + var z1 = g("yes" /* Yes */); + var z2 = g("no" /* No */); + var z3 = g(a); + var z4 = g(b); + var z5 = g(c); +} +function assertNever(x) { + throw new Error("Unexpected value"); +} +function f10(x) { + switch (x) { + case "yes" /* Yes */: return "true"; + case "no" /* No */: return "false"; + } +} +function f11(x) { + switch (x) { + case "yes" /* Yes */: return "true"; + case "no" /* No */: return "false"; + } + return assertNever(x); +} +function f12(x) { + if (x) { + x; + } + else { + x; + } +} +function f13(x) { + if (x === "yes" /* Yes */) { + x; + } + else { + x; + } +} +function f20(x) { + switch (x.kind) { + case "yes" /* Yes */: return x.a; + case "no" /* No */: return x.b; + } +} +function f21(x) { + switch (x.kind) { + case "yes" /* Yes */: return x.a; + case "no" /* No */: return x.b; + } + return assertNever(x); +} diff --git a/tests/baselines/reference/stringEnumLiteralTypes2.symbols b/tests/baselines/reference/stringEnumLiteralTypes2.symbols new file mode 100644 index 0000000000..f746c0430c --- /dev/null +++ b/tests/baselines/reference/stringEnumLiteralTypes2.symbols @@ -0,0 +1,353 @@ +=== tests/cases/conformance/types/literal/stringEnumLiteralTypes2.ts === +const enum Choice { Unknown = "", Yes = "yes", No = "no" }; +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Unknown : Symbol(Choice.Unknown, Decl(stringEnumLiteralTypes2.ts, 0, 19)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) + +type YesNo = Choice.Yes | Choice.No; +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes2.ts, 0, 59)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) + +type NoYes = Choice.No | Choice.Yes; +>NoYes : Symbol(NoYes, Decl(stringEnumLiteralTypes2.ts, 2, 36)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) + +type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; +>UnknownYesNo : Symbol(UnknownYesNo, Decl(stringEnumLiteralTypes2.ts, 3, 36)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Unknown : Symbol(Choice.Unknown, Decl(stringEnumLiteralTypes2.ts, 0, 19)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) + +function f1() { +>f1 : Symbol(f1, Decl(stringEnumLiteralTypes2.ts, 4, 60)) + + var a: YesNo; +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 7, 7), Decl(stringEnumLiteralTypes2.ts, 8, 7), Decl(stringEnumLiteralTypes2.ts, 9, 7), Decl(stringEnumLiteralTypes2.ts, 10, 7)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes2.ts, 0, 59)) + + var a: NoYes; +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 7, 7), Decl(stringEnumLiteralTypes2.ts, 8, 7), Decl(stringEnumLiteralTypes2.ts, 9, 7), Decl(stringEnumLiteralTypes2.ts, 10, 7)) +>NoYes : Symbol(NoYes, Decl(stringEnumLiteralTypes2.ts, 2, 36)) + + var a: Choice.Yes | Choice.No; +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 7, 7), Decl(stringEnumLiteralTypes2.ts, 8, 7), Decl(stringEnumLiteralTypes2.ts, 9, 7), Decl(stringEnumLiteralTypes2.ts, 10, 7)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) + + var a: Choice.No | Choice.Yes; +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 7, 7), Decl(stringEnumLiteralTypes2.ts, 8, 7), Decl(stringEnumLiteralTypes2.ts, 9, 7), Decl(stringEnumLiteralTypes2.ts, 10, 7)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +} + +function f2(a: YesNo, b: UnknownYesNo, c: Choice) { +>f2 : Symbol(f2, Decl(stringEnumLiteralTypes2.ts, 11, 1)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 13, 12)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes2.ts, 0, 59)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 13, 21)) +>UnknownYesNo : Symbol(UnknownYesNo, Decl(stringEnumLiteralTypes2.ts, 3, 36)) +>c : Symbol(c, Decl(stringEnumLiteralTypes2.ts, 13, 38)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) + + b = a; +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 13, 21)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 13, 12)) + + c = a; +>c : Symbol(c, Decl(stringEnumLiteralTypes2.ts, 13, 38)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 13, 12)) + + c = b; +>c : Symbol(c, Decl(stringEnumLiteralTypes2.ts, 13, 38)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 13, 21)) +} + +function f3(a: Choice.Yes, b: YesNo) { +>f3 : Symbol(f3, Decl(stringEnumLiteralTypes2.ts, 17, 1)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 19, 12)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes2.ts, 0, 59)) + + var x = a + b; +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 20, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) + + var y = a == b; +>y : Symbol(y, Decl(stringEnumLiteralTypes2.ts, 21, 7), Decl(stringEnumLiteralTypes2.ts, 22, 7), Decl(stringEnumLiteralTypes2.ts, 23, 7), Decl(stringEnumLiteralTypes2.ts, 24, 7), Decl(stringEnumLiteralTypes2.ts, 25, 7), Decl(stringEnumLiteralTypes2.ts, 26, 7), Decl(stringEnumLiteralTypes2.ts, 27, 7), Decl(stringEnumLiteralTypes2.ts, 28, 7), Decl(stringEnumLiteralTypes2.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) + + var y = a != b; +>y : Symbol(y, Decl(stringEnumLiteralTypes2.ts, 21, 7), Decl(stringEnumLiteralTypes2.ts, 22, 7), Decl(stringEnumLiteralTypes2.ts, 23, 7), Decl(stringEnumLiteralTypes2.ts, 24, 7), Decl(stringEnumLiteralTypes2.ts, 25, 7), Decl(stringEnumLiteralTypes2.ts, 26, 7), Decl(stringEnumLiteralTypes2.ts, 27, 7), Decl(stringEnumLiteralTypes2.ts, 28, 7), Decl(stringEnumLiteralTypes2.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) + + var y = a === b; +>y : Symbol(y, Decl(stringEnumLiteralTypes2.ts, 21, 7), Decl(stringEnumLiteralTypes2.ts, 22, 7), Decl(stringEnumLiteralTypes2.ts, 23, 7), Decl(stringEnumLiteralTypes2.ts, 24, 7), Decl(stringEnumLiteralTypes2.ts, 25, 7), Decl(stringEnumLiteralTypes2.ts, 26, 7), Decl(stringEnumLiteralTypes2.ts, 27, 7), Decl(stringEnumLiteralTypes2.ts, 28, 7), Decl(stringEnumLiteralTypes2.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) + + var y = a !== b; +>y : Symbol(y, Decl(stringEnumLiteralTypes2.ts, 21, 7), Decl(stringEnumLiteralTypes2.ts, 22, 7), Decl(stringEnumLiteralTypes2.ts, 23, 7), Decl(stringEnumLiteralTypes2.ts, 24, 7), Decl(stringEnumLiteralTypes2.ts, 25, 7), Decl(stringEnumLiteralTypes2.ts, 26, 7), Decl(stringEnumLiteralTypes2.ts, 27, 7), Decl(stringEnumLiteralTypes2.ts, 28, 7), Decl(stringEnumLiteralTypes2.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) + + var y = a > b; +>y : Symbol(y, Decl(stringEnumLiteralTypes2.ts, 21, 7), Decl(stringEnumLiteralTypes2.ts, 22, 7), Decl(stringEnumLiteralTypes2.ts, 23, 7), Decl(stringEnumLiteralTypes2.ts, 24, 7), Decl(stringEnumLiteralTypes2.ts, 25, 7), Decl(stringEnumLiteralTypes2.ts, 26, 7), Decl(stringEnumLiteralTypes2.ts, 27, 7), Decl(stringEnumLiteralTypes2.ts, 28, 7), Decl(stringEnumLiteralTypes2.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) + + var y = a < b; +>y : Symbol(y, Decl(stringEnumLiteralTypes2.ts, 21, 7), Decl(stringEnumLiteralTypes2.ts, 22, 7), Decl(stringEnumLiteralTypes2.ts, 23, 7), Decl(stringEnumLiteralTypes2.ts, 24, 7), Decl(stringEnumLiteralTypes2.ts, 25, 7), Decl(stringEnumLiteralTypes2.ts, 26, 7), Decl(stringEnumLiteralTypes2.ts, 27, 7), Decl(stringEnumLiteralTypes2.ts, 28, 7), Decl(stringEnumLiteralTypes2.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) + + var y = a >= b; +>y : Symbol(y, Decl(stringEnumLiteralTypes2.ts, 21, 7), Decl(stringEnumLiteralTypes2.ts, 22, 7), Decl(stringEnumLiteralTypes2.ts, 23, 7), Decl(stringEnumLiteralTypes2.ts, 24, 7), Decl(stringEnumLiteralTypes2.ts, 25, 7), Decl(stringEnumLiteralTypes2.ts, 26, 7), Decl(stringEnumLiteralTypes2.ts, 27, 7), Decl(stringEnumLiteralTypes2.ts, 28, 7), Decl(stringEnumLiteralTypes2.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) + + var y = a <= b; +>y : Symbol(y, Decl(stringEnumLiteralTypes2.ts, 21, 7), Decl(stringEnumLiteralTypes2.ts, 22, 7), Decl(stringEnumLiteralTypes2.ts, 23, 7), Decl(stringEnumLiteralTypes2.ts, 24, 7), Decl(stringEnumLiteralTypes2.ts, 25, 7), Decl(stringEnumLiteralTypes2.ts, 26, 7), Decl(stringEnumLiteralTypes2.ts, 27, 7), Decl(stringEnumLiteralTypes2.ts, 28, 7), Decl(stringEnumLiteralTypes2.ts, 29, 7)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 19, 12)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) + + var y = !b; +>y : Symbol(y, Decl(stringEnumLiteralTypes2.ts, 21, 7), Decl(stringEnumLiteralTypes2.ts, 22, 7), Decl(stringEnumLiteralTypes2.ts, 23, 7), Decl(stringEnumLiteralTypes2.ts, 24, 7), Decl(stringEnumLiteralTypes2.ts, 25, 7), Decl(stringEnumLiteralTypes2.ts, 26, 7), Decl(stringEnumLiteralTypes2.ts, 27, 7), Decl(stringEnumLiteralTypes2.ts, 28, 7), Decl(stringEnumLiteralTypes2.ts, 29, 7)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 19, 26)) +} + +declare function g(x: Choice.Yes): string; +>g : Symbol(g, Decl(stringEnumLiteralTypes2.ts, 30, 1), Decl(stringEnumLiteralTypes2.ts, 32, 42), Decl(stringEnumLiteralTypes2.ts, 33, 42)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 32, 19)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) + +declare function g(x: Choice.No): boolean; +>g : Symbol(g, Decl(stringEnumLiteralTypes2.ts, 30, 1), Decl(stringEnumLiteralTypes2.ts, 32, 42), Decl(stringEnumLiteralTypes2.ts, 33, 42)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 33, 19)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) + +declare function g(x: Choice): number; +>g : Symbol(g, Decl(stringEnumLiteralTypes2.ts, 30, 1), Decl(stringEnumLiteralTypes2.ts, 32, 42), Decl(stringEnumLiteralTypes2.ts, 33, 42)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 34, 19)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) + +function f5(a: YesNo, b: UnknownYesNo, c: Choice) { +>f5 : Symbol(f5, Decl(stringEnumLiteralTypes2.ts, 34, 38)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 36, 12)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes2.ts, 0, 59)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 36, 21)) +>UnknownYesNo : Symbol(UnknownYesNo, Decl(stringEnumLiteralTypes2.ts, 3, 36)) +>c : Symbol(c, Decl(stringEnumLiteralTypes2.ts, 36, 38)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) + + var z1 = g(Choice.Yes); +>z1 : Symbol(z1, Decl(stringEnumLiteralTypes2.ts, 37, 7)) +>g : Symbol(g, Decl(stringEnumLiteralTypes2.ts, 30, 1), Decl(stringEnumLiteralTypes2.ts, 32, 42), Decl(stringEnumLiteralTypes2.ts, 33, 42)) +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) + + var z2 = g(Choice.No); +>z2 : Symbol(z2, Decl(stringEnumLiteralTypes2.ts, 38, 7)) +>g : Symbol(g, Decl(stringEnumLiteralTypes2.ts, 30, 1), Decl(stringEnumLiteralTypes2.ts, 32, 42), Decl(stringEnumLiteralTypes2.ts, 33, 42)) +>Choice.No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) + + var z3 = g(a); +>z3 : Symbol(z3, Decl(stringEnumLiteralTypes2.ts, 39, 7)) +>g : Symbol(g, Decl(stringEnumLiteralTypes2.ts, 30, 1), Decl(stringEnumLiteralTypes2.ts, 32, 42), Decl(stringEnumLiteralTypes2.ts, 33, 42)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 36, 12)) + + var z4 = g(b); +>z4 : Symbol(z4, Decl(stringEnumLiteralTypes2.ts, 40, 7)) +>g : Symbol(g, Decl(stringEnumLiteralTypes2.ts, 30, 1), Decl(stringEnumLiteralTypes2.ts, 32, 42), Decl(stringEnumLiteralTypes2.ts, 33, 42)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 36, 21)) + + var z5 = g(c); +>z5 : Symbol(z5, Decl(stringEnumLiteralTypes2.ts, 41, 7)) +>g : Symbol(g, Decl(stringEnumLiteralTypes2.ts, 30, 1), Decl(stringEnumLiteralTypes2.ts, 32, 42), Decl(stringEnumLiteralTypes2.ts, 33, 42)) +>c : Symbol(c, Decl(stringEnumLiteralTypes2.ts, 36, 38)) +} + +function assertNever(x: never): never { +>assertNever : Symbol(assertNever, Decl(stringEnumLiteralTypes2.ts, 42, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 44, 21)) + + throw new Error("Unexpected value"); +>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +} + +function f10(x: YesNo) { +>f10 : Symbol(f10, Decl(stringEnumLiteralTypes2.ts, 46, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 48, 13)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes2.ts, 0, 59)) + + switch (x) { +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 48, 13)) + + case Choice.Yes: return "true"; +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) + + case Choice.No: return "false"; +>Choice.No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) + } +} + +function f11(x: YesNo) { +>f11 : Symbol(f11, Decl(stringEnumLiteralTypes2.ts, 53, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 55, 13)) +>YesNo : Symbol(YesNo, Decl(stringEnumLiteralTypes2.ts, 0, 59)) + + switch (x) { +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 55, 13)) + + case Choice.Yes: return "true"; +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) + + case Choice.No: return "false"; +>Choice.No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) + } + return assertNever(x); +>assertNever : Symbol(assertNever, Decl(stringEnumLiteralTypes2.ts, 42, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 55, 13)) +} + +function f12(x: UnknownYesNo) { +>f12 : Symbol(f12, Decl(stringEnumLiteralTypes2.ts, 61, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 63, 13)) +>UnknownYesNo : Symbol(UnknownYesNo, Decl(stringEnumLiteralTypes2.ts, 3, 36)) + + if (x) { +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 63, 13)) + + x; +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 63, 13)) + } + else { + x; +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 63, 13)) + } +} + +function f13(x: UnknownYesNo) { +>f13 : Symbol(f13, Decl(stringEnumLiteralTypes2.ts, 70, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 72, 13)) +>UnknownYesNo : Symbol(UnknownYesNo, Decl(stringEnumLiteralTypes2.ts, 3, 36)) + + if (x === Choice.Yes) { +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 72, 13)) +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) + + x; +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 72, 13)) + } + else { + x; +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 72, 13)) + } +} + +type Item = +>Item : Symbol(Item, Decl(stringEnumLiteralTypes2.ts, 79, 1)) + + { kind: Choice.Yes, a: string } | +>kind : Symbol(kind, Decl(stringEnumLiteralTypes2.ts, 82, 5)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 82, 23)) + + { kind: Choice.No, b: string }; +>kind : Symbol(kind, Decl(stringEnumLiteralTypes2.ts, 83, 5)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 83, 22)) + +function f20(x: Item) { +>f20 : Symbol(f20, Decl(stringEnumLiteralTypes2.ts, 83, 35)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 85, 13)) +>Item : Symbol(Item, Decl(stringEnumLiteralTypes2.ts, 79, 1)) + + switch (x.kind) { +>x.kind : Symbol(kind, Decl(stringEnumLiteralTypes2.ts, 82, 5), Decl(stringEnumLiteralTypes2.ts, 83, 5)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 85, 13)) +>kind : Symbol(kind, Decl(stringEnumLiteralTypes2.ts, 82, 5), Decl(stringEnumLiteralTypes2.ts, 83, 5)) + + case Choice.Yes: return x.a; +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>x.a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 82, 23)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 85, 13)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 82, 23)) + + case Choice.No: return x.b; +>Choice.No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) +>x.b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 83, 22)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 85, 13)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 83, 22)) + } +} + +function f21(x: Item) { +>f21 : Symbol(f21, Decl(stringEnumLiteralTypes2.ts, 90, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 92, 13)) +>Item : Symbol(Item, Decl(stringEnumLiteralTypes2.ts, 79, 1)) + + switch (x.kind) { +>x.kind : Symbol(kind, Decl(stringEnumLiteralTypes2.ts, 82, 5), Decl(stringEnumLiteralTypes2.ts, 83, 5)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 92, 13)) +>kind : Symbol(kind, Decl(stringEnumLiteralTypes2.ts, 82, 5), Decl(stringEnumLiteralTypes2.ts, 83, 5)) + + case Choice.Yes: return x.a; +>Choice.Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>Yes : Symbol(Choice.Yes, Decl(stringEnumLiteralTypes2.ts, 0, 33)) +>x.a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 82, 23)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 92, 13)) +>a : Symbol(a, Decl(stringEnumLiteralTypes2.ts, 82, 23)) + + case Choice.No: return x.b; +>Choice.No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) +>Choice : Symbol(Choice, Decl(stringEnumLiteralTypes2.ts, 0, 0)) +>No : Symbol(Choice.No, Decl(stringEnumLiteralTypes2.ts, 0, 46)) +>x.b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 83, 22)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 92, 13)) +>b : Symbol(b, Decl(stringEnumLiteralTypes2.ts, 83, 22)) + } + return assertNever(x); +>assertNever : Symbol(assertNever, Decl(stringEnumLiteralTypes2.ts, 42, 1)) +>x : Symbol(x, Decl(stringEnumLiteralTypes2.ts, 92, 13)) +} diff --git a/tests/baselines/reference/stringEnumLiteralTypes2.types b/tests/baselines/reference/stringEnumLiteralTypes2.types new file mode 100644 index 0000000000..7e4a51d9ae --- /dev/null +++ b/tests/baselines/reference/stringEnumLiteralTypes2.types @@ -0,0 +1,383 @@ +=== tests/cases/conformance/types/literal/stringEnumLiteralTypes2.ts === +const enum Choice { Unknown = "", Yes = "yes", No = "no" }; +>Choice : Choice +>Unknown : Choice.Unknown +>"" : "" +>Yes : Choice.Yes +>"yes" : "yes" +>No : Choice.No +>"no" : "no" + +type YesNo = Choice.Yes | Choice.No; +>YesNo : YesNo +>Choice : any +>Yes : Choice.Yes +>Choice : any +>No : Choice.No + +type NoYes = Choice.No | Choice.Yes; +>NoYes : YesNo +>Choice : any +>No : Choice.No +>Choice : any +>Yes : Choice.Yes + +type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; +>UnknownYesNo : Choice +>Choice : any +>Unknown : Choice.Unknown +>Choice : any +>Yes : Choice.Yes +>Choice : any +>No : Choice.No + +function f1() { +>f1 : () => void + + var a: YesNo; +>a : YesNo +>YesNo : YesNo + + var a: NoYes; +>a : YesNo +>NoYes : YesNo + + var a: Choice.Yes | Choice.No; +>a : YesNo +>Choice : any +>Yes : Choice.Yes +>Choice : any +>No : Choice.No + + var a: Choice.No | Choice.Yes; +>a : YesNo +>Choice : any +>No : Choice.No +>Choice : any +>Yes : Choice.Yes +} + +function f2(a: YesNo, b: UnknownYesNo, c: Choice) { +>f2 : (a: YesNo, b: Choice, c: Choice) => void +>a : YesNo +>YesNo : YesNo +>b : Choice +>UnknownYesNo : Choice +>c : Choice +>Choice : Choice + + b = a; +>b = a : YesNo +>b : Choice +>a : YesNo + + c = a; +>c = a : YesNo +>c : Choice +>a : YesNo + + c = b; +>c = b : YesNo +>c : Choice +>b : YesNo +} + +function f3(a: Choice.Yes, b: YesNo) { +>f3 : (a: Choice.Yes, b: YesNo) => void +>a : Choice.Yes +>Choice : any +>Yes : Choice.Yes +>b : YesNo +>YesNo : YesNo + + var x = a + b; +>x : string +>a + b : string +>a : Choice.Yes +>b : YesNo + + var y = a == b; +>y : boolean +>a == b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a != b; +>y : boolean +>a != b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a === b; +>y : boolean +>a === b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a !== b; +>y : boolean +>a !== b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a > b; +>y : boolean +>a > b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a < b; +>y : boolean +>a < b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a >= b; +>y : boolean +>a >= b : boolean +>a : Choice.Yes +>b : YesNo + + var y = a <= b; +>y : boolean +>a <= b : boolean +>a : Choice.Yes +>b : YesNo + + var y = !b; +>y : boolean +>!b : false +>b : YesNo +} + +declare function g(x: Choice.Yes): string; +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>x : Choice.Yes +>Choice : any +>Yes : Choice.Yes + +declare function g(x: Choice.No): boolean; +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>x : Choice.No +>Choice : any +>No : Choice.No + +declare function g(x: Choice): number; +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>x : Choice +>Choice : Choice + +function f5(a: YesNo, b: UnknownYesNo, c: Choice) { +>f5 : (a: YesNo, b: Choice, c: Choice) => void +>a : YesNo +>YesNo : YesNo +>b : Choice +>UnknownYesNo : Choice +>c : Choice +>Choice : Choice + + var z1 = g(Choice.Yes); +>z1 : string +>g(Choice.Yes) : string +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes + + var z2 = g(Choice.No); +>z2 : boolean +>g(Choice.No) : boolean +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>Choice.No : Choice.No +>Choice : typeof Choice +>No : Choice.No + + var z3 = g(a); +>z3 : number +>g(a) : number +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>a : YesNo + + var z4 = g(b); +>z4 : number +>g(b) : number +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>b : Choice + + var z5 = g(c); +>z5 : number +>g(c) : number +>g : { (x: Choice.Yes): string; (x: Choice.No): boolean; (x: Choice): number; } +>c : Choice +} + +function assertNever(x: never): never { +>assertNever : (x: never) => never +>x : never + + throw new Error("Unexpected value"); +>new Error("Unexpected value") : Error +>Error : ErrorConstructor +>"Unexpected value" : "Unexpected value" +} + +function f10(x: YesNo) { +>f10 : (x: YesNo) => "true" | "false" +>x : YesNo +>YesNo : YesNo + + switch (x) { +>x : YesNo + + case Choice.Yes: return "true"; +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes +>"true" : "true" + + case Choice.No: return "false"; +>Choice.No : Choice.No +>Choice : typeof Choice +>No : Choice.No +>"false" : "false" + } +} + +function f11(x: YesNo) { +>f11 : (x: YesNo) => "true" | "false" +>x : YesNo +>YesNo : YesNo + + switch (x) { +>x : YesNo + + case Choice.Yes: return "true"; +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes +>"true" : "true" + + case Choice.No: return "false"; +>Choice.No : Choice.No +>Choice : typeof Choice +>No : Choice.No +>"false" : "false" + } + return assertNever(x); +>assertNever(x) : never +>assertNever : (x: never) => never +>x : never +} + +function f12(x: UnknownYesNo) { +>f12 : (x: Choice) => void +>x : Choice +>UnknownYesNo : Choice + + if (x) { +>x : Choice + + x; +>x : YesNo + } + else { + x; +>x : Choice.Unknown + } +} + +function f13(x: UnknownYesNo) { +>f13 : (x: Choice) => void +>x : Choice +>UnknownYesNo : Choice + + if (x === Choice.Yes) { +>x === Choice.Yes : boolean +>x : Choice +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes + + x; +>x : Choice.Yes + } + else { + x; +>x : Choice.Unknown | Choice.No + } +} + +type Item = +>Item : Item + + { kind: Choice.Yes, a: string } | +>kind : Choice.Yes +>Choice : any +>Yes : Choice.Yes +>a : string + + { kind: Choice.No, b: string }; +>kind : Choice.No +>Choice : any +>No : Choice.No +>b : string + +function f20(x: Item) { +>f20 : (x: Item) => string +>x : Item +>Item : Item + + switch (x.kind) { +>x.kind : YesNo +>x : Item +>kind : YesNo + + case Choice.Yes: return x.a; +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes +>x.a : string +>x : { kind: Choice.Yes; a: string; } +>a : string + + case Choice.No: return x.b; +>Choice.No : Choice.No +>Choice : typeof Choice +>No : Choice.No +>x.b : string +>x : { kind: Choice.No; b: string; } +>b : string + } +} + +function f21(x: Item) { +>f21 : (x: Item) => string +>x : Item +>Item : Item + + switch (x.kind) { +>x.kind : YesNo +>x : Item +>kind : YesNo + + case Choice.Yes: return x.a; +>Choice.Yes : Choice.Yes +>Choice : typeof Choice +>Yes : Choice.Yes +>x.a : string +>x : { kind: Choice.Yes; a: string; } +>a : string + + case Choice.No: return x.b; +>Choice.No : Choice.No +>Choice : typeof Choice +>No : Choice.No +>x.b : string +>x : { kind: Choice.No; b: string; } +>b : string + } + return assertNever(x); +>assertNever(x) : never +>assertNever : (x: never) => never +>x : never +} diff --git a/tests/baselines/reference/stringEnumLiteralTypes3.errors.txt b/tests/baselines/reference/stringEnumLiteralTypes3.errors.txt new file mode 100644 index 0000000000..7feed87d82 --- /dev/null +++ b/tests/baselines/reference/stringEnumLiteralTypes3.errors.txt @@ -0,0 +1,166 @@ +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(10,5): error TS2322: Type 'YesNo' is not assignable to type 'Choice.Yes'. + Type 'Choice.No' is not assignable to type 'Choice.Yes'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(11,5): error TS2322: Type 'Choice' is not assignable to type 'Choice.Yes'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(12,5): error TS2322: Type 'Choice' is not assignable to type 'Choice.Yes'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(18,5): error TS2322: Type 'Choice' is not assignable to type 'YesNo'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(19,5): error TS2322: Type 'Choice' is not assignable to type 'YesNo'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(37,5): error TS2322: Type 'Choice.Unknown' is not assignable to type 'Choice.Yes'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(39,5): error TS2322: Type 'Choice.No' is not assignable to type 'Choice.Yes'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(40,5): error TS2322: Type 'Choice.Unknown' is not assignable to type 'YesNo'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(52,5): error TS2365: Operator '===' cannot be applied to types 'Choice.Yes' and 'Choice.Unknown'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(54,5): error TS2365: Operator '===' cannot be applied to types 'Choice.Yes' and 'Choice.No'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(55,5): error TS2365: Operator '===' cannot be applied to types 'YesNo' and 'Choice.Unknown'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(87,14): error TS2678: Type 'Choice.Unknown' is not comparable to type 'Choice.Yes'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(89,14): error TS2678: Type 'Choice.No' is not comparable to type 'Choice.Yes'. +tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts(96,14): error TS2678: Type 'Choice.Unknown' is not comparable to type 'YesNo'. + + +==== tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts (14 errors) ==== + const enum Choice { Unknown = "", Yes = "yes", No = "no" }; + + type Yes = Choice.Yes; + type YesNo = Choice.Yes | Choice.No; + type NoYes = Choice.No | Choice.Yes; + type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; + + function f1(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a = a; + a = b; + ~ +!!! error TS2322: Type 'YesNo' is not assignable to type 'Choice.Yes'. +!!! error TS2322: Type 'Choice.No' is not assignable to type 'Choice.Yes'. + a = c; + ~ +!!! error TS2322: Type 'Choice' is not assignable to type 'Choice.Yes'. + a = d; + ~ +!!! error TS2322: Type 'Choice' is not assignable to type 'Choice.Yes'. + } + + function f2(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + b = a; + b = b; + b = c; + ~ +!!! error TS2322: Type 'Choice' is not assignable to type 'YesNo'. + b = d; + ~ +!!! error TS2322: Type 'Choice' is not assignable to type 'YesNo'. + } + + function f3(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + c = a; + c = b; + c = c; + c = d; + } + + function f4(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + d = a; + d = b; + d = c; + d = d; + } + + function f5(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a = Choice.Unknown; + ~ +!!! error TS2322: Type 'Choice.Unknown' is not assignable to type 'Choice.Yes'. + a = Choice.Yes; + a = Choice.No; + ~ +!!! error TS2322: Type 'Choice.No' is not assignable to type 'Choice.Yes'. + b = Choice.Unknown; + ~ +!!! error TS2322: Type 'Choice.Unknown' is not assignable to type 'YesNo'. + b = Choice.Yes; + b = Choice.No; + c = Choice.Unknown; + c = Choice.Yes; + c = Choice.No; + d = Choice.Unknown; + d = Choice.Yes; + d = Choice.No; + } + + function f6(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a === Choice.Unknown; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types 'Choice.Yes' and 'Choice.Unknown'. + a === Choice.Yes; + a === Choice.No; + ~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types 'Choice.Yes' and 'Choice.No'. + b === Choice.Unknown; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types 'YesNo' and 'Choice.Unknown'. + b === Choice.Yes; + b === Choice.No; + c === Choice.Unknown; + c === Choice.Yes; + c === Choice.No; + d === Choice.Unknown; + d === Choice.Yes; + d === Choice.No; + } + + function f7(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a === a; + a === b; + a === c; + a === d; + b === a; + b === b; + b === c; + b === d; + c === a; + c === b; + c === c; + c === d; + d === a; + d === b; + d === c; + d === d; + } + + function f10(x: Yes): Yes { + switch (x) { + case Choice.Unknown: return x; + ~~~~~~~~~~~~~~ +!!! error TS2678: Type 'Choice.Unknown' is not comparable to type 'Choice.Yes'. + case Choice.Yes: return x; + case Choice.No: return x; + ~~~~~~~~~ +!!! error TS2678: Type 'Choice.No' is not comparable to type 'Choice.Yes'. + } + return x; + } + + function f11(x: YesNo): YesNo { + switch (x) { + case Choice.Unknown: return x; + ~~~~~~~~~~~~~~ +!!! error TS2678: Type 'Choice.Unknown' is not comparable to type 'YesNo'. + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; + } + + function f12(x: UnknownYesNo): UnknownYesNo { + switch (x) { + case Choice.Unknown: return x; + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; + } + + function f13(x: Choice): Choice { + switch (x) { + case Choice.Unknown: return x; + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; + } \ No newline at end of file diff --git a/tests/baselines/reference/stringEnumLiteralTypes3.js b/tests/baselines/reference/stringEnumLiteralTypes3.js new file mode 100644 index 0000000000..7e2699460b --- /dev/null +++ b/tests/baselines/reference/stringEnumLiteralTypes3.js @@ -0,0 +1,225 @@ +//// [stringEnumLiteralTypes3.ts] +const enum Choice { Unknown = "", Yes = "yes", No = "no" }; + +type Yes = Choice.Yes; +type YesNo = Choice.Yes | Choice.No; +type NoYes = Choice.No | Choice.Yes; +type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; + +function f1(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a = a; + a = b; + a = c; + a = d; +} + +function f2(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + b = a; + b = b; + b = c; + b = d; +} + +function f3(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + c = a; + c = b; + c = c; + c = d; +} + +function f4(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + d = a; + d = b; + d = c; + d = d; +} + +function f5(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a = Choice.Unknown; + a = Choice.Yes; + a = Choice.No; + b = Choice.Unknown; + b = Choice.Yes; + b = Choice.No; + c = Choice.Unknown; + c = Choice.Yes; + c = Choice.No; + d = Choice.Unknown; + d = Choice.Yes; + d = Choice.No; +} + +function f6(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a === Choice.Unknown; + a === Choice.Yes; + a === Choice.No; + b === Choice.Unknown; + b === Choice.Yes; + b === Choice.No; + c === Choice.Unknown; + c === Choice.Yes; + c === Choice.No; + d === Choice.Unknown; + d === Choice.Yes; + d === Choice.No; +} + +function f7(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a === a; + a === b; + a === c; + a === d; + b === a; + b === b; + b === c; + b === d; + c === a; + c === b; + c === c; + c === d; + d === a; + d === b; + d === c; + d === d; +} + +function f10(x: Yes): Yes { + switch (x) { + case Choice.Unknown: return x; + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; +} + +function f11(x: YesNo): YesNo { + switch (x) { + case Choice.Unknown: return x; + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; +} + +function f12(x: UnknownYesNo): UnknownYesNo { + switch (x) { + case Choice.Unknown: return x; + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; +} + +function f13(x: Choice): Choice { + switch (x) { + case Choice.Unknown: return x; + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; +} + +//// [stringEnumLiteralTypes3.js] +; +function f1(a, b, c, d) { + a = a; + a = b; + a = c; + a = d; +} +function f2(a, b, c, d) { + b = a; + b = b; + b = c; + b = d; +} +function f3(a, b, c, d) { + c = a; + c = b; + c = c; + c = d; +} +function f4(a, b, c, d) { + d = a; + d = b; + d = c; + d = d; +} +function f5(a, b, c, d) { + a = "" /* Unknown */; + a = "yes" /* Yes */; + a = "no" /* No */; + b = "" /* Unknown */; + b = "yes" /* Yes */; + b = "no" /* No */; + c = "" /* Unknown */; + c = "yes" /* Yes */; + c = "no" /* No */; + d = "" /* Unknown */; + d = "yes" /* Yes */; + d = "no" /* No */; +} +function f6(a, b, c, d) { + a === "" /* Unknown */; + a === "yes" /* Yes */; + a === "no" /* No */; + b === "" /* Unknown */; + b === "yes" /* Yes */; + b === "no" /* No */; + c === "" /* Unknown */; + c === "yes" /* Yes */; + c === "no" /* No */; + d === "" /* Unknown */; + d === "yes" /* Yes */; + d === "no" /* No */; +} +function f7(a, b, c, d) { + a === a; + a === b; + a === c; + a === d; + b === a; + b === b; + b === c; + b === d; + c === a; + c === b; + c === c; + c === d; + d === a; + d === b; + d === c; + d === d; +} +function f10(x) { + switch (x) { + case "" /* Unknown */: return x; + case "yes" /* Yes */: return x; + case "no" /* No */: return x; + } + return x; +} +function f11(x) { + switch (x) { + case "" /* Unknown */: return x; + case "yes" /* Yes */: return x; + case "no" /* No */: return x; + } + return x; +} +function f12(x) { + switch (x) { + case "" /* Unknown */: return x; + case "yes" /* Yes */: return x; + case "no" /* No */: return x; + } + return x; +} +function f13(x) { + switch (x) { + case "" /* Unknown */: return x; + case "yes" /* Yes */: return x; + case "no" /* No */: return x; + } + return x; +} diff --git a/tests/baselines/reference/subtypesOfUnion.errors.txt b/tests/baselines/reference/subtypesOfUnion.errors.txt index fade537781..7cbca6cc40 100644 --- a/tests/baselines/reference/subtypesOfUnion.errors.txt +++ b/tests/baselines/reference/subtypesOfUnion.errors.txt @@ -12,21 +12,21 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOf tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(28,5): error TS2411: Property 'foo16' of type 'T' is not assignable to string index type 'string | number'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(29,5): error TS2411: Property 'foo17' of type 'Object' is not assignable to string index type 'string | number'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(30,5): error TS2411: Property 'foo18' of type '{}' is not assignable to string index type 'string | number'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(35,5): error TS2411: Property 'foo2' of type 'string' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(37,5): error TS2411: Property 'foo4' of type 'boolean' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(39,5): error TS2411: Property 'foo6' of type 'Date' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(40,5): error TS2411: Property 'foo7' of type 'RegExp' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(41,5): error TS2411: Property 'foo8' of type '{ bar: number; }' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(42,5): error TS2411: Property 'foo9' of type 'I8' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(43,5): error TS2411: Property 'foo10' of type 'A' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(44,5): error TS2411: Property 'foo11' of type 'A2' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(45,5): error TS2411: Property 'foo12' of type '(x: any) => number' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(46,5): error TS2411: Property 'foo13' of type '(x: T) => T' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(47,5): error TS2411: Property 'foo14' of type 'typeof f' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(48,5): error TS2411: Property 'foo15' of type 'typeof c' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(49,5): error TS2411: Property 'foo16' of type 'T' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(50,5): error TS2411: Property 'foo17' of type 'Object' is not assignable to string index type 'number | E'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(51,5): error TS2411: Property 'foo18' of type '{}' is not assignable to string index type 'number | E'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(35,5): error TS2411: Property 'foo2' of type 'string' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(37,5): error TS2411: Property 'foo4' of type 'boolean' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(39,5): error TS2411: Property 'foo6' of type 'Date' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(40,5): error TS2411: Property 'foo7' of type 'RegExp' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(41,5): error TS2411: Property 'foo8' of type '{ bar: number; }' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(42,5): error TS2411: Property 'foo9' of type 'I8' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(43,5): error TS2411: Property 'foo10' of type 'A' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(44,5): error TS2411: Property 'foo11' of type 'A2' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(45,5): error TS2411: Property 'foo12' of type '(x: any) => number' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(46,5): error TS2411: Property 'foo13' of type '(x: T) => T' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(47,5): error TS2411: Property 'foo14' of type 'typeof f' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(48,5): error TS2411: Property 'foo15' of type 'typeof c' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(49,5): error TS2411: Property 'foo16' of type 'T' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(50,5): error TS2411: Property 'foo17' of type 'Object' is not assignable to string index type 'number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts(51,5): error TS2411: Property 'foo18' of type '{}' is not assignable to string index type 'number'. ==== tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOfUnion.ts (29 errors) ==== @@ -94,49 +94,49 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/subtypesOf foo: any; // ok foo2: string; // error ~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'string' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo2' of type 'string' is not assignable to string index type 'number'. foo3: number; // ok foo4: boolean; // error ~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo4' of type 'boolean' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo4' of type 'boolean' is not assignable to string index type 'number'. foo5: E; // ok foo6: Date; // error ~~~~~~~~~~~ -!!! error TS2411: Property 'foo6' of type 'Date' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo6' of type 'Date' is not assignable to string index type 'number'. foo7: RegExp; // error ~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo7' of type 'RegExp' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo7' of type 'RegExp' is not assignable to string index type 'number'. foo8: { bar: number }; // error ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo8' of type '{ bar: number; }' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo8' of type '{ bar: number; }' is not assignable to string index type 'number'. foo9: I8; // error ~~~~~~~~~ -!!! error TS2411: Property 'foo9' of type 'I8' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo9' of type 'I8' is not assignable to string index type 'number'. foo10: A; // error ~~~~~~~~~ -!!! error TS2411: Property 'foo10' of type 'A' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo10' of type 'A' is not assignable to string index type 'number'. foo11: A2; // error ~~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo11' of type 'A2' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo11' of type 'A2' is not assignable to string index type 'number'. foo12: (x) => number; //error ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo12' of type '(x: any) => number' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo12' of type '(x: any) => number' is not assignable to string index type 'number'. foo13: (x: T) => T; // error ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo13' of type '(x: T) => T' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo13' of type '(x: T) => T' is not assignable to string index type 'number'. foo14: typeof f; // error ~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo14' of type 'typeof f' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo14' of type 'typeof f' is not assignable to string index type 'number'. foo15: typeof c; // error ~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo15' of type 'typeof c' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo15' of type 'typeof c' is not assignable to string index type 'number'. foo16: T; // error ~~~~~~~~~ -!!! error TS2411: Property 'foo16' of type 'T' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo16' of type 'T' is not assignable to string index type 'number'. foo17: Object; // error ~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo17' of type 'Object' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo17' of type 'Object' is not assignable to string index type 'number'. foo18: {}; // error ~~~~~~~~~~ -!!! error TS2411: Property 'foo18' of type '{}' is not assignable to string index type 'number | E'. +!!! error TS2411: Property 'foo18' of type '{}' is not assignable to string index type 'number'. } \ No newline at end of file diff --git a/tests/baselines/reference/tsxAttributeResolution5.errors.txt b/tests/baselines/reference/tsxAttributeResolution5.errors.txt index 0c6be5f35d..f5af99d6f0 100644 --- a/tests/baselines/reference/tsxAttributeResolution5.errors.txt +++ b/tests/baselines/reference/tsxAttributeResolution5.errors.txt @@ -1,8 +1,10 @@ -tests/cases/conformance/jsx/file.tsx(21,16): error TS2322: Type '{ x: number; }' is not assignable to type 'Attribs1'. - Types of property 'x' are incompatible. - Type 'number' is not assignable to type 'string'. -tests/cases/conformance/jsx/file.tsx(25,16): error TS2322: Type '{ y: string; }' is not assignable to type 'Attribs1'. - Property 'x' is missing in type '{ y: string; }'. +tests/cases/conformance/jsx/file.tsx(21,16): error TS2322: Type 'T' is not assignable to type 'Attribs1'. + Type '{ x: number; }' is not assignable to type 'Attribs1'. + Types of property 'x' are incompatible. + Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsx/file.tsx(25,16): error TS2322: Type 'T' is not assignable to type 'Attribs1'. + Type '{ y: string; }' is not assignable to type 'Attribs1'. + Property 'x' is missing in type '{ y: string; }'. tests/cases/conformance/jsx/file.tsx(29,8): error TS2322: Type '{}' is not assignable to type 'Attribs1'. Property 'x' is missing in type '{}'. @@ -30,16 +32,18 @@ tests/cases/conformance/jsx/file.tsx(29,8): error TS2322: Type '{}' is not assig function make2 (obj: T) { return ; // Error (x is number, not string) ~~~~~~~~ -!!! error TS2322: Type '{ x: number; }' is not assignable to type 'Attribs1'. -!!! error TS2322: Types of property 'x' are incompatible. -!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! error TS2322: Type 'T' is not assignable to type 'Attribs1'. +!!! error TS2322: Type '{ x: number; }' is not assignable to type 'Attribs1'. +!!! error TS2322: Types of property 'x' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'string'. } function make3 (obj: T) { return ; // Error, missing x ~~~~~~~~ -!!! error TS2322: Type '{ y: string; }' is not assignable to type 'Attribs1'. -!!! error TS2322: Property 'x' is missing in type '{ y: string; }'. +!!! error TS2322: Type 'T' is not assignable to type 'Attribs1'. +!!! error TS2322: Type '{ y: string; }' is not assignable to type 'Attribs1'. +!!! error TS2322: Property 'x' is missing in type '{ y: string; }'. } diff --git a/tests/baselines/reference/tsxGenericAttributesType9.js b/tests/baselines/reference/tsxGenericAttributesType9.js new file mode 100644 index 0000000000..b7b90736ad --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType9.js @@ -0,0 +1,40 @@ +//// [file.tsx] +import React = require('react'); + +export function makeP

(Ctor: React.ComponentClass

): React.ComponentClass

{ + return class extends React.PureComponent { + public render(): JSX.Element { + return ( + + ); + } + }; +} + +//// [file.jsx] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var React = require("react"); +function makeP(Ctor) { + return (function (_super) { + __extends(class_1, _super); + function class_1() { + return _super !== null && _super.apply(this, arguments) || this; + } + class_1.prototype.render = function () { + return (); + }; + return class_1; + }(React.PureComponent)); +} +exports.makeP = makeP; diff --git a/tests/baselines/reference/tsxGenericAttributesType9.symbols b/tests/baselines/reference/tsxGenericAttributesType9.symbols new file mode 100644 index 0000000000..f4df2e7940 --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType9.symbols @@ -0,0 +1,37 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : Symbol(React, Decl(file.tsx, 0, 0)) + +export function makeP

(Ctor: React.ComponentClass

): React.ComponentClass

{ +>makeP : Symbol(makeP, Decl(file.tsx, 0, 32)) +>P : Symbol(P, Decl(file.tsx, 2, 22)) +>Ctor : Symbol(Ctor, Decl(file.tsx, 2, 25)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>ComponentClass : Symbol(React.ComponentClass, Decl(react.d.ts, 204, 5)) +>P : Symbol(P, Decl(file.tsx, 2, 22)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>ComponentClass : Symbol(React.ComponentClass, Decl(react.d.ts, 204, 5)) +>P : Symbol(P, Decl(file.tsx, 2, 22)) + + return class extends React.PureComponent { +>React.PureComponent : Symbol(React.PureComponent, Decl(react.d.ts, 179, 5)) +>React : Symbol(React, Decl(file.tsx, 0, 0)) +>PureComponent : Symbol(React.PureComponent, Decl(react.d.ts, 179, 5)) +>P : Symbol(P, Decl(file.tsx, 2, 22)) + + public render(): JSX.Element { +>render : Symbol((Anonymous class).render, Decl(file.tsx, 3, 52)) +>JSX : Symbol(JSX, Decl(react.d.ts, 2352, 1)) +>Element : Symbol(JSX.Element, Decl(react.d.ts, 2355, 27)) + + return ( + +>Ctor : Symbol(Ctor, Decl(file.tsx, 2, 25)) +>this.props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) +>this : Symbol((Anonymous class), Decl(file.tsx, 3, 7)) +>props : Symbol(React.Component.props, Decl(react.d.ts, 166, 37)) + + ); + } + }; +} diff --git a/tests/baselines/reference/tsxGenericAttributesType9.types b/tests/baselines/reference/tsxGenericAttributesType9.types new file mode 100644 index 0000000000..a1d7efc49b --- /dev/null +++ b/tests/baselines/reference/tsxGenericAttributesType9.types @@ -0,0 +1,41 @@ +=== tests/cases/conformance/jsx/file.tsx === +import React = require('react'); +>React : typeof React + +export function makeP

(Ctor: React.ComponentClass

): React.ComponentClass

{ +>makeP :

(Ctor: React.ComponentClass

) => React.ComponentClass

+>P : P +>Ctor : React.ComponentClass

+>React : any +>ComponentClass : React.ComponentClass

+>P : P +>React : any +>ComponentClass : React.ComponentClass

+>P : P + + return class extends React.PureComponent { +>class extends React.PureComponent { public render(): JSX.Element { return ( ); } } : typeof (Anonymous class) +>React.PureComponent : React.PureComponent +>React : typeof React +>PureComponent : typeof React.PureComponent +>P : P + + public render(): JSX.Element { +>render : () => JSX.Element +>JSX : any +>Element : JSX.Element + + return ( +>( ) : JSX.Element + + +> : JSX.Element +>Ctor : React.ComponentClass

+>this.props : P & { children?: React.ReactNode; } +>this : this +>props : P & { children?: React.ReactNode; } + + ); + } + }; +} diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt index c8ff457711..7e94011688 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt +++ b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments2.errors.txt @@ -1,10 +1,9 @@ -tests/cases/conformance/jsx/file.tsx(8,34): error TS2322: Type '{ ignore-prop: 10; prop: number; }' is not assignable to type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'. - Type '{ ignore-prop: 10; prop: number; }' is not assignable to type '{ prop: number; "ignore-prop": string; }'. +tests/cases/conformance/jsx/file.tsx(8,34): error TS2322: Type 'T & { ignore-prop: 10; }' is not assignable to type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'. + Type 'T & { ignore-prop: 10; }' is not assignable to type '{ prop: number; "ignore-prop": string; }'. Types of property '"ignore-prop"' are incompatible. Type '10' is not assignable to type 'string'. -tests/cases/conformance/jsx/file.tsx(13,34): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { prop: {}; "ignore-prop": string; }'. - Type '{}' is not assignable to type '{ prop: {}; "ignore-prop": string; }'. - Property 'prop' is missing in type '{}'. +tests/cases/conformance/jsx/file.tsx(13,34): error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { prop: {}; "ignore-prop": string; }'. + Type 'T' is not assignable to type '{ prop: {}; "ignore-prop": string; }'. tests/cases/conformance/jsx/file.tsx(20,19): error TS2322: Type '{ func: (a: number, b: string) => void; }' is not assignable to type 'IntrinsicAttributes & { func: (arg: number) => void; }'. Type '{ func: (a: number, b: string) => void; }' is not assignable to type '{ func: (arg: number) => void; }'. Types of property 'func' are incompatible. @@ -25,8 +24,8 @@ tests/cases/conformance/jsx/file.tsx(31,10): error TS2453: The type argument for function Bar(arg: T) { let a1 = ; ~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ ignore-prop: 10; prop: number; }' is not assignable to type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'. -!!! error TS2322: Type '{ ignore-prop: 10; prop: number; }' is not assignable to type '{ prop: number; "ignore-prop": string; }'. +!!! error TS2322: Type 'T & { ignore-prop: 10; }' is not assignable to type 'IntrinsicAttributes & { prop: number; "ignore-prop": string; }'. +!!! error TS2322: Type 'T & { ignore-prop: 10; }' is not assignable to type '{ prop: number; "ignore-prop": string; }'. !!! error TS2322: Types of property '"ignore-prop"' are incompatible. !!! error TS2322: Type '10' is not assignable to type 'string'. } @@ -35,9 +34,8 @@ tests/cases/conformance/jsx/file.tsx(31,10): error TS2453: The type argument for function Baz(arg: T) { let a0 = ~~~~~~~~ -!!! error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { prop: {}; "ignore-prop": string; }'. -!!! error TS2322: Type '{}' is not assignable to type '{ prop: {}; "ignore-prop": string; }'. -!!! error TS2322: Property 'prop' is missing in type '{}'. +!!! error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { prop: {}; "ignore-prop": string; }'. +!!! error TS2322: Type 'T' is not assignable to type '{ prop: {}; "ignore-prop": string; }'. } declare function Link(l: {func: (arg: U)=>void}): JSX.Element; diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt index d9b50ef31c..311cfaed86 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt +++ b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt @@ -1,9 +1,12 @@ tests/cases/conformance/jsx/file.tsx(9,33): error TS2322: Type '{ a: number; }' is not assignable to type 'IntrinsicAttributes & { b: {}; a: number; }'. Type '{ a: number; }' is not assignable to type '{ b: {}; a: number; }'. Property 'b' is missing in type '{ a: number; }'. -tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. - Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. - Property 'a' is missing in type '{ b: number; }'. +tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. + Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. + Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. + Type 'T' is not assignable to type '{ b: number; a: {}; }'. + Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. + Property 'a' is missing in type '{ b: number; }'. ==== tests/cases/conformance/jsx/file.tsx (2 errors) ==== @@ -22,7 +25,10 @@ tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type '{ b: number; }' !!! error TS2322: Property 'b' is missing in type '{ a: number; }'. let a2 = // missing a ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. -!!! error TS2322: Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. -!!! error TS2322: Property 'a' is missing in type '{ b: number; }'. +!!! error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. +!!! error TS2322: Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'. +!!! error TS2322: Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. +!!! error TS2322: Type 'T' is not assignable to type '{ b: number; a: {}; }'. +!!! error TS2322: Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'. +!!! error TS2322: Property 'a' is missing in type '{ b: number; }'. } \ No newline at end of file diff --git a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments5.errors.txt b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments5.errors.txt index b92375797e..57a2ae556f 100644 --- a/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments5.errors.txt +++ b/tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments5.errors.txt @@ -1,7 +1,11 @@ +tests/cases/conformance/jsx/file.tsx(15,14): error TS2605: JSX element type 'Element' is not a constructor function for JSX elements. + Property 'render' is missing in type 'Element'. +tests/cases/conformance/jsx/file.tsx(15,15): error TS2453: The type argument for type parameter 'U' cannot be inferred from the usage. Consider specifying the type arguments explicitly. + Type argument candidate 'number' is not a valid type argument because it is not a supertype of candidate '"hello"'. tests/cases/conformance/jsx/file.tsx(16,42): error TS2339: Property 'prop1' does not exist on type 'IntrinsicAttributes & { prop: number; }'. -==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== +==== tests/cases/conformance/jsx/file.tsx (3 errors) ==== import React = require('react') declare function Component(l: U): JSX.Element; @@ -17,6 +21,12 @@ tests/cases/conformance/jsx/file.tsx(16,42): error TS2339: Property 'prop1' does let a1 = ; // U is number let a2 = ; // U is number let a3 = ; // U is "hello" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2605: JSX element type 'Element' is not a constructor function for JSX elements. +!!! error TS2605: Property 'render' is missing in type 'Element'. + ~~~~~~~~~~~~~~~~~ +!!! error TS2453: The type argument for type parameter 'U' cannot be inferred from the usage. Consider specifying the type arguments explicitly. +!!! error TS2453: Type argument candidate 'number' is not a valid type argument because it is not a supertype of candidate '"hello"'. let a4 = ; // U is "hello" ~~~~~~~~~~~~~ !!! error TS2339: Property 'prop1' does not exist on type 'IntrinsicAttributes & { prop: number; }'. diff --git a/tests/baselines/reference/typeArgumentInferenceWithObjectLiteral.errors.txt b/tests/baselines/reference/typeArgumentInferenceWithObjectLiteral.errors.txt index e82e7e020d..c1352bedb9 100644 --- a/tests/baselines/reference/typeArgumentInferenceWithObjectLiteral.errors.txt +++ b/tests/baselines/reference/typeArgumentInferenceWithObjectLiteral.errors.txt @@ -1,10 +1,8 @@ -tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithObjectLiteral.ts(30,10): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly. - Type argument candidate 'E1' is not a valid type argument because it is not a supertype of candidate '0'. tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithObjectLiteral.ts(35,10): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly. Type argument candidate 'E1' is not a valid type argument because it is not a supertype of candidate 'E2'. -==== tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithObjectLiteral.ts (2 errors) ==== +==== tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithObjectLiteral.ts (1 errors) ==== interface Computed { read(): T; write(value: T); @@ -35,9 +33,6 @@ tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithObjec var v1 = f1({ w: x => x, r: () => 0 }, 0); var v1 = f1({ w: x => x, r: () => 0 }, E1.X); var v1 = f1({ w: x => x, r: () => E1.X }, 0); - ~~ -!!! error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly. -!!! error TS2453: Type argument candidate 'E1' is not a valid type argument because it is not a supertype of candidate '0'. var v2: E1; var v2 = f1({ w: x => x, r: () => E1.X }, E1.X); diff --git a/tests/baselines/reference/unicodeStringLiteral.js b/tests/baselines/reference/unicodeStringLiteral.js new file mode 100644 index 0000000000..c69f7aa7e9 --- /dev/null +++ b/tests/baselines/reference/unicodeStringLiteral.js @@ -0,0 +1,5 @@ +//// [unicodeStringLiteral.ts] +var ੳ = "Ü­ਲĭ"; + +//// [unicodeStringLiteral.js] +var ੳ = "Ü­ਲĭ"; diff --git a/tests/baselines/reference/unicodeStringLiteral.symbols b/tests/baselines/reference/unicodeStringLiteral.symbols new file mode 100644 index 0000000000..f48111c060 --- /dev/null +++ b/tests/baselines/reference/unicodeStringLiteral.symbols @@ -0,0 +1,4 @@ +=== tests/cases/compiler/unicodeStringLiteral.ts === +var ੳ = "Ü­ਲĭ"; +>ੳ : Symbol(ੳ, Decl(unicodeStringLiteral.ts, 0, 3)) + diff --git a/tests/baselines/reference/unicodeStringLiteral.types b/tests/baselines/reference/unicodeStringLiteral.types new file mode 100644 index 0000000000..e98f5987ed --- /dev/null +++ b/tests/baselines/reference/unicodeStringLiteral.types @@ -0,0 +1,5 @@ +=== tests/cases/compiler/unicodeStringLiteral.ts === +var ੳ = "Ü­ਲĭ"; +>ੳ : string +>"Ü­ਲĭ" : "Ü­ਲ\u000Eĭ" + diff --git a/tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.errors.txt b/tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.errors.txt index 013b5d9a99..ddf5da8881 100644 --- a/tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.errors.txt +++ b/tests/baselines/reference/unionSubtypeIfEveryConstituentTypeIsSubtype.errors.txt @@ -1,37 +1,36 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(15,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'number'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(21,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'string'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(22,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'string'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(22,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'string'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(28,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'boolean'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(29,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'boolean'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(29,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'boolean'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(35,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'Date'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(36,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'Date'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(36,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'Date'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(42,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'RegExp'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(43,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'RegExp'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(43,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'RegExp'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(49,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '{ bar: number; }'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(50,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '{ bar: number; }'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(50,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type '{ bar: number; }'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(56,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'number[]'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(57,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'number[]'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(57,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'number[]'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(63,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'I8'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(64,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'I8'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(64,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'I8'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(70,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'A'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(71,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'A'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(71,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'A'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(77,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'A2'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(78,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'A2'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(78,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'A2'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(84,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '(x: any) => number'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(85,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '(x: any) => number'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(85,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type '(x: any) => number'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(91,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '(x: T) => T'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(92,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '(x: T) => T'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(92,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type '(x: T) => T'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(99,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'E2'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(100,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'E2'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(110,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'typeof f'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(111,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'typeof f'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(111,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'typeof f'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(121,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'typeof c'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(122,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'typeof c'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(122,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'typeof c'. tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(128,5): error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'T'. -tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(129,5): error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'T'. +tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts(129,5): error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'T'. -==== tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts (31 errors) ==== +==== tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubtypeIfEveryConstituentTypeIsSubtype.ts (30 errors) ==== enum e { e1, e2 @@ -59,7 +58,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'string'. foo2: e | number; // error e and number both not subtype of string ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'string'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'string'. } // error cases @@ -70,7 +69,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'boolean'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'boolean'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'boolean'. } @@ -81,7 +80,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'Date'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'Date'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'Date'. } @@ -92,7 +91,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'RegExp'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'RegExp'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'RegExp'. } @@ -103,7 +102,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '{ bar: number; }'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '{ bar: number; }'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type '{ bar: number; }'. } @@ -114,7 +113,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'number[]'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'number[]'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'number[]'. } @@ -125,7 +124,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'I8'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'I8'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'I8'. } class A { foo: number; } @@ -136,7 +135,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'A'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'A'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'A'. } class A2 { foo: T; } @@ -147,7 +146,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'A2'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'A2'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'A2'. } @@ -158,7 +157,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '(x: any) => number'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '(x: any) => number'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type '(x: any) => number'. } @@ -169,7 +168,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type '(x: T) => T'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type '(x: T) => T'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type '(x: T) => T'. } @@ -180,8 +179,6 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'E2'. foo2: e | number; - ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'E2'. } @@ -196,7 +193,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'typeof f'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'typeof f'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'typeof f'. } @@ -211,7 +208,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'typeof c'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'typeof c'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'typeof c'. } @@ -222,7 +219,7 @@ tests/cases/conformance/types/typeRelationships/subtypesAndSuperTypes/unionSubty !!! error TS2411: Property 'foo' of type 'string | number' is not assignable to string index type 'T'. foo2: e | number; ~~~~~~~~~~~~~~~~~ -!!! error TS2411: Property 'foo2' of type 'number | e' is not assignable to string index type 'T'. +!!! error TS2411: Property 'foo2' of type 'number' is not assignable to string index type 'T'. } interface I19 { diff --git a/tests/cases/compiler/objectLiteralFreshnessWithSpread.ts b/tests/cases/compiler/objectLiteralFreshnessWithSpread.ts new file mode 100644 index 0000000000..7e8044e064 --- /dev/null +++ b/tests/cases/compiler/objectLiteralFreshnessWithSpread.ts @@ -0,0 +1,2 @@ +let x = { b: 1, extra: 2 } +let xx: { a, b } = { a: 1, ...x, z: 3 } // error for 'z', no error for 'extra' diff --git a/tests/cases/compiler/unicodeStringLiteral.ts b/tests/cases/compiler/unicodeStringLiteral.ts new file mode 100644 index 0000000000..fa2e128330 --- /dev/null +++ b/tests/cases/compiler/unicodeStringLiteral.ts @@ -0,0 +1 @@ +var ੳ = "Ü­ਲĭ"; \ No newline at end of file diff --git a/tests/cases/conformance/enums/enumBasics.ts b/tests/cases/conformance/enums/enumBasics.ts index 1e13454071..0a0f9d920c 100644 --- a/tests/cases/conformance/enums/enumBasics.ts +++ b/tests/cases/conformance/enums/enumBasics.ts @@ -11,9 +11,9 @@ var x: number = E1.A; // Enum object type is anonymous with properties of the enum type and numeric indexer var e = E1; var e: { - readonly A: E1; - readonly B: E1; - readonly C: E1; + readonly A: E1.A; + readonly B: E1.B; + readonly C: E1.C; readonly [n: number]: string; }; var e: typeof E1; diff --git a/tests/cases/conformance/enums/enumClassification.ts b/tests/cases/conformance/enums/enumClassification.ts new file mode 100644 index 0000000000..bbb0598408 --- /dev/null +++ b/tests/cases/conformance/enums/enumClassification.ts @@ -0,0 +1,80 @@ +// @declaration: true + +// An enum type where each member has no initializer or an initializer that specififes +// a numeric literal, a string literal, or a single identifier naming another member in +// the enum type is classified as a literal enum type. An enum type that doesn't adhere +// to this pattern is classified as a numeric enum type. + +// Examples of literal enum types + +enum E01 { + A +} + +enum E02 { + A = 123 +} + +enum E03 { + A = "hello" +} + +enum E04 { + A, + B, + C +} + +enum E05 { + A, + B = 10, + C +} + +enum E06 { + A = "one", + B = "two", + C = "three" +} + +enum E07 { + A, + B, + C = "hi", + D = 10, + E, + F = "bye" +} + +enum E08 { + A = 10, + B = "hello", + C = A, + D = B, + E = C, +} + +// Examples of numeric enum types with only constant members + +enum E10 {} + +enum E11 { + A = +0, + B, + C +} + +enum E12 { + A = 1 << 0, + B = 1 << 1, + C = 1 << 2 +} + +// Examples of numeric enum types with constant and computed members + +enum E20 { + A = "foo".length, + B = A + 1, + C = +"123", + D = Math.sin(1) +} diff --git a/tests/cases/conformance/enums/enumErrors.ts b/tests/cases/conformance/enums/enumErrors.ts index ed438bb3ed..99de3d4bc0 100644 --- a/tests/cases/conformance/enums/enumErrors.ts +++ b/tests/cases/conformance/enums/enumErrors.ts @@ -23,8 +23,17 @@ enum E10 { // Enum with computed member intializer of other types enum E11 { - A = '', + A = true, B = new Date(), C = window, D = {} } + +// Enum with string valued member and computed member initializers +enum E12 { + A = '', + B = new Date(), + C = window, + D = {}, + E = 1 + 1, +} diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts new file mode 100644 index 0000000000..9151f52f00 --- /dev/null +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts @@ -0,0 +1,38 @@ +declare function all(a?: number, b?: number): void; +declare function weird(a?: number | string, b?: number | string): void; +declare function prefix(s: string, a?: number, b?: number): void; +declare function rest(s: string, a?: number, b?: number, ...rest: number[]): void; +declare function normal(s: string): void; +declare function thunk(): string; + +declare var ns: number[]; +declare var mixed: (number | string)[]; +declare var tuple: [number, string]; + +// good +all(...ns) +weird(...ns) +weird(...mixed) +weird(...tuple) +prefix("a", ...ns) +rest("d", ...ns) + + +// this covers the arguments case +normal("g", ...ns) +normal("h", ...mixed) +normal("i", ...tuple) +thunk(...ns) +thunk(...mixed) +thunk(...tuple) + +// bad +all(...mixed) +all(...tuple) +prefix("b", ...mixed) +prefix("c", ...tuple) +rest("e", ...mixed) +rest("f", ...tuple) +prefix(...ns) // required parameters are required +prefix(...mixed) +prefix(...tuple) diff --git a/tests/cases/conformance/jsx/tsxGenericAttributesType9.tsx b/tests/cases/conformance/jsx/tsxGenericAttributesType9.tsx new file mode 100644 index 0000000000..a9466a4398 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxGenericAttributesType9.tsx @@ -0,0 +1,16 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +export function makeP

(Ctor: React.ComponentClass

): React.ComponentClass

{ + return class extends React.PureComponent { + public render(): JSX.Element { + return ( + + ); + } + }; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/literal/stringEnumLiteralTypes1.ts b/tests/cases/conformance/types/literal/stringEnumLiteralTypes1.ts new file mode 100644 index 0000000000..11be7c9060 --- /dev/null +++ b/tests/cases/conformance/types/literal/stringEnumLiteralTypes1.ts @@ -0,0 +1,99 @@ +const enum Choice { Unknown = "", Yes = "yes", No = "no" }; + +type YesNo = Choice.Yes | Choice.No; +type NoYes = Choice.No | Choice.Yes; +type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; + +function f1() { + var a: YesNo; + var a: NoYes; + var a: Choice.Yes | Choice.No; + var a: Choice.No | Choice.Yes; +} + +function f2(a: YesNo, b: UnknownYesNo, c: Choice) { + b = a; + c = a; + c = b; +} + +function f3(a: Choice.Yes, b: YesNo) { + var x = a + b; + var y = a == b; + var y = a != b; + var y = a === b; + var y = a !== b; + var y = a > b; + var y = a < b; + var y = a >= b; + var y = a <= b; + var y = !b; +} + +declare function g(x: Choice.Yes): string; +declare function g(x: Choice.No): boolean; +declare function g(x: Choice): number; + +function f5(a: YesNo, b: UnknownYesNo, c: Choice) { + var z1 = g(Choice.Yes); + var z2 = g(Choice.No); + var z3 = g(a); + var z4 = g(b); + var z5 = g(c); +} + +function assertNever(x: never): never { + throw new Error("Unexpected value"); +} + +function f10(x: YesNo) { + switch (x) { + case Choice.Yes: return "true"; + case Choice.No: return "false"; + } +} + +function f11(x: YesNo) { + switch (x) { + case Choice.Yes: return "true"; + case Choice.No: return "false"; + } + return assertNever(x); +} + +function f12(x: UnknownYesNo) { + if (x) { + x; + } + else { + x; + } +} + +function f13(x: UnknownYesNo) { + if (x === Choice.Yes) { + x; + } + else { + x; + } +} + +type Item = + { kind: Choice.Yes, a: string } | + { kind: Choice.No, b: string }; + +function f20(x: Item) { + switch (x.kind) { + case Choice.Yes: return x.a; + case Choice.No: return x.b; + } +} + +function f21(x: Item) { + switch (x.kind) { + case Choice.Yes: return x.a; + case Choice.No: return x.b; + } + return assertNever(x); +} \ No newline at end of file diff --git a/tests/cases/conformance/types/literal/stringEnumLiteralTypes2.ts b/tests/cases/conformance/types/literal/stringEnumLiteralTypes2.ts new file mode 100644 index 0000000000..f6a71fcaa7 --- /dev/null +++ b/tests/cases/conformance/types/literal/stringEnumLiteralTypes2.ts @@ -0,0 +1,101 @@ +// @strictNullChecks: true + +const enum Choice { Unknown = "", Yes = "yes", No = "no" }; + +type YesNo = Choice.Yes | Choice.No; +type NoYes = Choice.No | Choice.Yes; +type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; + +function f1() { + var a: YesNo; + var a: NoYes; + var a: Choice.Yes | Choice.No; + var a: Choice.No | Choice.Yes; +} + +function f2(a: YesNo, b: UnknownYesNo, c: Choice) { + b = a; + c = a; + c = b; +} + +function f3(a: Choice.Yes, b: YesNo) { + var x = a + b; + var y = a == b; + var y = a != b; + var y = a === b; + var y = a !== b; + var y = a > b; + var y = a < b; + var y = a >= b; + var y = a <= b; + var y = !b; +} + +declare function g(x: Choice.Yes): string; +declare function g(x: Choice.No): boolean; +declare function g(x: Choice): number; + +function f5(a: YesNo, b: UnknownYesNo, c: Choice) { + var z1 = g(Choice.Yes); + var z2 = g(Choice.No); + var z3 = g(a); + var z4 = g(b); + var z5 = g(c); +} + +function assertNever(x: never): never { + throw new Error("Unexpected value"); +} + +function f10(x: YesNo) { + switch (x) { + case Choice.Yes: return "true"; + case Choice.No: return "false"; + } +} + +function f11(x: YesNo) { + switch (x) { + case Choice.Yes: return "true"; + case Choice.No: return "false"; + } + return assertNever(x); +} + +function f12(x: UnknownYesNo) { + if (x) { + x; + } + else { + x; + } +} + +function f13(x: UnknownYesNo) { + if (x === Choice.Yes) { + x; + } + else { + x; + } +} + +type Item = + { kind: Choice.Yes, a: string } | + { kind: Choice.No, b: string }; + +function f20(x: Item) { + switch (x.kind) { + case Choice.Yes: return x.a; + case Choice.No: return x.b; + } +} + +function f21(x: Item) { + switch (x.kind) { + case Choice.Yes: return x.a; + case Choice.No: return x.b; + } + return assertNever(x); +} \ No newline at end of file diff --git a/tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts b/tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts new file mode 100644 index 0000000000..f296fd875f --- /dev/null +++ b/tests/cases/conformance/types/literal/stringEnumLiteralTypes3.ts @@ -0,0 +1,119 @@ +const enum Choice { Unknown = "", Yes = "yes", No = "no" }; + +type Yes = Choice.Yes; +type YesNo = Choice.Yes | Choice.No; +type NoYes = Choice.No | Choice.Yes; +type UnknownYesNo = Choice.Unknown | Choice.Yes | Choice.No; + +function f1(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a = a; + a = b; + a = c; + a = d; +} + +function f2(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + b = a; + b = b; + b = c; + b = d; +} + +function f3(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + c = a; + c = b; + c = c; + c = d; +} + +function f4(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + d = a; + d = b; + d = c; + d = d; +} + +function f5(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a = Choice.Unknown; + a = Choice.Yes; + a = Choice.No; + b = Choice.Unknown; + b = Choice.Yes; + b = Choice.No; + c = Choice.Unknown; + c = Choice.Yes; + c = Choice.No; + d = Choice.Unknown; + d = Choice.Yes; + d = Choice.No; +} + +function f6(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a === Choice.Unknown; + a === Choice.Yes; + a === Choice.No; + b === Choice.Unknown; + b === Choice.Yes; + b === Choice.No; + c === Choice.Unknown; + c === Choice.Yes; + c === Choice.No; + d === Choice.Unknown; + d === Choice.Yes; + d === Choice.No; +} + +function f7(a: Yes, b: YesNo, c: UnknownYesNo, d: Choice) { + a === a; + a === b; + a === c; + a === d; + b === a; + b === b; + b === c; + b === d; + c === a; + c === b; + c === c; + c === d; + d === a; + d === b; + d === c; + d === d; +} + +function f10(x: Yes): Yes { + switch (x) { + case Choice.Unknown: return x; + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; +} + +function f11(x: YesNo): YesNo { + switch (x) { + case Choice.Unknown: return x; + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; +} + +function f12(x: UnknownYesNo): UnknownYesNo { + switch (x) { + case Choice.Unknown: return x; + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; +} + +function f13(x: Choice): Choice { + switch (x) { + case Choice.Unknown: return x; + case Choice.Yes: return x; + case Choice.No: return x; + } + return x; +} \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesString.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesString.ts index 4b595c6eda..9d42faada3 100644 --- a/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesString.ts +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceIndexSignaturesString.ts @@ -1,11 +1,11 @@ /// //// interface I { -//// [x: string]: X; +//// [Ƚ: string]: X; //// } //// //// class C implements I {[| |]} verify.rangeAfterCodeFix(` - [x: string]: number; + [Ƚ: string]: number; `); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceInheritsAbstractMethod.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceInheritsAbstractMethod.ts index c141592823..7bb230a2df 100644 --- a/tests/cases/fourslash/codeFixClassImplementInterfaceInheritsAbstractMethod.ts +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceInheritsAbstractMethod.ts @@ -2,12 +2,12 @@ //// abstract class C1 { } //// abstract class C2 { -//// abstract f1(); +//// abstract fA(); //// } //// interface I1 extends C1, C2 { } //// class C3 implements I1 {[| |]} -verify.rangeAfterCodeFix(`f1(){ +verify.rangeAfterCodeFix(`fA(){ throw new Error("Method not implemented."); } `); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMemberNestedTypeAlias.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMemberNestedTypeAlias.ts new file mode 100644 index 0000000000..5aa5f1a4e5 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMemberNestedTypeAlias.ts @@ -0,0 +1,16 @@ +/// + +//// type Either = { val: T } | Error; +//// interface I { +//// x: Either>; +//// foo(x: Either>): void; +//// } +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + x: Either>; + foo(x: Either>): void { + throw new Error("Method not implemented."); + } +`); + diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMemberTypeAlias.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMemberTypeAlias.ts new file mode 100644 index 0000000000..44981302a1 --- /dev/null +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMemberTypeAlias.ts @@ -0,0 +1,12 @@ +/// + +//// type MyType = [string, number]; +//// interface I { x: MyType; test(a: MyType): void; } +//// class C implements I {[| |]} + +verify.rangeAfterCodeFix(` + x: [string, number]; + test(a: [string, number]): void { + throw new Error("Method not implemented."); + } +`); diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements2.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements2.ts index e5100b88f6..946b6495c5 100644 --- a/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements2.ts +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMultipleImplements2.ts @@ -4,7 +4,7 @@ //// x: number; //// } //// interface I2 { -//// y: number; +//// y: "𣋝ઢȴ¬⏊"; //// } //// //// class C implements I1,I2 {[| @@ -12,7 +12,7 @@ //// } verify.rangeAfterCodeFix(` -y: number; +y: "𣋝ઢȴ¬⏊"; `); verify.not.codeFixAvailable(); diff --git a/tests/cases/fourslash/completionListOfUnion.ts b/tests/cases/fourslash/completionListOfUnion.ts index 6026615f8c..5ffaf89e5b 100644 --- a/tests/cases/fourslash/completionListOfUnion.ts +++ b/tests/cases/fourslash/completionListOfUnion.ts @@ -2,17 +2,19 @@ // @strictNullChecks: true -// Non-objects should be skipped, so `| number | null` should have no effect on completions. -////const x: { a: number, b: number } | { a: string, c: string } | { b: boolean } | number | null = { /*x*/ }; +// Primitives should be skipped, so `| number | null | undefined` should have no effect on completions. +////const x: { a: number, b: number } | { a: string, c: string } | { b: boolean } | number | null | undefined = { /*x*/ }; ////interface I { a: number; } ////function f(...args: Array) {} ////f({ /*f*/ }); goTo.marker("x"); +verify.completionListCount(3); verify.completionListContains("a", "(property) a: string | number"); verify.completionListContains("b", "(property) b: number | boolean"); verify.completionListContains("c", "(property) c: string"); goTo.marker("f"); verify.completionListContains("a", "(property) a: number"); +// Also contains array members diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport04.ts b/tests/cases/fourslash/findAllRefsForDefaultExport04.ts new file mode 100644 index 0000000000..c8fdb0a614 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsForDefaultExport04.ts @@ -0,0 +1,16 @@ +/// + +// @Filename: /a.ts +////const [|{| "isWriteAccess": true, "isDefinition": true |}a|] = 0; +////export default [|a|]; + +// @Filename: /b.ts +////import [|{| "isWriteAccess": true, "isDefinition": true |}a|] from "./a"; +////[|a|]; + +const [r0, r1, r2, r3] = test.ranges(); +verify.referenceGroups([r0, r1], [ + { definition: "const a: 0", ranges: [r0, r1] }, + { definition: "import a", ranges: [r2, r3] } +]); +verify.singleReferenceGroup("import a", [r2, r3]); diff --git a/tests/cases/fourslash/tsxQuickInfo6.ts b/tests/cases/fourslash/tsxQuickInfo6.ts index 88d9435e80..2b65dc7667 100644 --- a/tests/cases/fourslash/tsxQuickInfo6.ts +++ b/tests/cases/fourslash/tsxQuickInfo6.ts @@ -15,5 +15,5 @@ verify.quickInfos({ 1: "function ComponentSpecific(l: {\n prop: number;\n}): any", - 2: "function ComponentSpecific<\"hello\">(l: {\n prop: \"hello\";\n}): any" + 2: "function ComponentSpecific(l: {\n prop: U;\n}): any" }); diff --git a/tests/cases/fourslash/tsxQuickInfo7.ts b/tests/cases/fourslash/tsxQuickInfo7.ts index 3e66fb655f..cf08aa53e9 100644 --- a/tests/cases/fourslash/tsxQuickInfo7.ts +++ b/tests/cases/fourslash/tsxQuickInfo7.ts @@ -24,6 +24,6 @@ verify.quickInfos({ 3: "function OverloadComponent(attr: {\n b: string;\n a: boolean;\n}): any (+2 overloads)", 4: "function OverloadComponent(attr: {\n b: number;\n a?: string;\n \"ignore-prop\": boolean;\n}): any (+2 overloads)", 5: "function OverloadComponent(): any (+2 overloads)", - 6: "function OverloadComponent(attr: {\n b: number;\n a: boolean;\n}): any (+2 overloads)", - 7: "function OverloadComponent(attr: {\n b: string;\n a: boolean;\n}): any (+2 overloads)" + 6: "function OverloadComponent(): any (+2 overloads)", + 7: "function OverloadComponent(): any (+2 overloads)", });