diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2328b7e3d68a4..ab64f41ac2446 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -631,6 +631,7 @@ namespace ts { const literalTypes = createMap(); const indexedAccessTypes = createMap(); const substitutionTypes = createMap(); + const structuralTags = createMap(); const evolvingArrayTypes: EvolvingArrayType[] = []; const undefinedProperties = createMap() as UnderscoreEscapedMap; @@ -3799,6 +3800,10 @@ namespace ts { if (type.flags & TypeFlags.Substitution) { return typeToTypeNodeHelper((type).typeVariable, context); } + if (type.flags & TypeFlags.StructuralTag) { + context.approximateLength += 4; + return createTypeOperatorNode(SyntaxKind.TagKeyword, typeToTypeNodeHelper((type as StructuralTagType).type, context)); + } return Debug.fail("Should be unreachable."); @@ -8103,6 +8108,9 @@ namespace ts { if (t.flags & TypeFlags.Substitution) { return getBaseConstraint((t).substitute); } + if (t.flags & TypeFlags.StructuralTag) { + return unknownType; + } return t; } } @@ -9924,10 +9932,10 @@ namespace ts { return links.resolvedType; } - function addTypeToIntersection(typeSet: Map, includes: TypeFlags, type: Type) { + function addTypeToIntersection(typeSet: Map, includes: TypeFlags, type: Type, tagSet: Map) { const flags = type.flags; if (flags & TypeFlags.Intersection) { - return addTypesToIntersection(typeSet, includes, (type).types); + return addTypesToIntersection(typeSet, includes, (type).types, tagSet); } if (isEmptyAnonymousObjectType(type)) { if (!(includes & TypeFlags.IncludesEmptyObject)) { @@ -9939,6 +9947,9 @@ namespace ts { if (flags & TypeFlags.AnyOrUnknown) { if (type === wildcardType) includes |= TypeFlags.IncludesWildcard; } + else if (flags & TypeFlags.StructuralTag) { + tagSet.set(type.id.toString(), type as StructuralTagType); + } else if ((strictNullChecks || !(flags & TypeFlags.Nullable)) && !typeSet.has(type.id.toString())) { if (type.flags & TypeFlags.Unit && includes & TypeFlags.Unit) { // We have seen two distinct unit types which means we should reduce to an @@ -9954,9 +9965,23 @@ namespace ts { // Add the given types to the given type set. Order is preserved, freshness is removed from literal // types, duplicates are removed, and nested types of the given kind are flattened into the set. - function addTypesToIntersection(typeSet: Map, includes: TypeFlags, types: ReadonlyArray) { + function addTypesToIntersection(typeSet: Map, includes: TypeFlags, types: ReadonlyArray, tagSet?: Map | undefined) { + const isTopLevel = !tagSet; + tagSet = tagSet || createMap(); for (const type of types) { - includes = addTypeToIntersection(typeSet, includes, getRegularTypeOfLiteralType(type)); + includes = addTypeToIntersection(typeSet, includes, getRegularTypeOfLiteralType(type), tagSet); + } + if (isTopLevel && tagSet.size) { + let tag: StructuralTagType; + if (tagSet.size === 1) { + tag = tagSet.values().next().value; + } + else { + const tagTypes: Type[] = []; + tagSet.forEach(t => tagTypes.push(t.type)); + tag = getStructuralTagForType(getIntersectionType(tagTypes)); + } + typeSet.set(tag.id.toString(), tag); } return includes; } @@ -10258,6 +10283,11 @@ namespace ts { case SyntaxKind.ReadonlyKeyword: links.resolvedType = getTypeFromTypeNode(node.type); break; + case SyntaxKind.TagKeyword: + const aliasSymbol = getAliasSymbolForTypeNode(node); + const aliasParams = getTypeArgumentsForAliasSymbol(aliasSymbol); + links.resolvedType = getStructuralTagForType(getTypeFromTypeNode(node.type), aliasSymbol, aliasParams); + break; default: throw Debug.assertNever(node.operator); } @@ -10272,6 +10302,19 @@ namespace ts { return type; } + function getStructuralTagForType(type: Type, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]) { + const tid = "" + getTypeId(type); + if (structuralTags.has(tid)) { + return structuralTags.get(tid)!; + } + const tag = createType(TypeFlags.StructuralTag) as StructuralTagType; + tag.type = type; + tag.aliasSymbol = aliasSymbol; + tag.aliasTypeArguments = aliasTypeArguments; + structuralTags.set(tid, tag); + return tag; + } + /** * Returns if a type is or consists of a JSLiteral object type * In addition to objects which are directly literals, @@ -11706,6 +11749,10 @@ namespace ts { return sub; } } + if (flags & TypeFlags.StructuralTag) { + const newType = instantiateType((type as StructuralTagType).type, mapper); + return newType !== type ? getStructuralTagForType(newType, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; + } return type; } @@ -13422,6 +13469,9 @@ namespace ts { if (flags & TypeFlags.Substitution) { return isRelatedTo((source).substitute, (target).substitute, /*reportErrors*/ false); } + if (flags & TypeFlags.StructuralTag) { + return isRelatedTo((source).type, (target).type, /*reportErrors*/ false); + } return Ternary.False; } @@ -13524,6 +13574,12 @@ namespace ts { } } } + else if (target.flags & TypeFlags.StructuralTag) { + if (source.flags & TypeFlags.StructuralTag) { + return isRelatedTo((source as StructuralTagType).type, (target as StructuralTagType).type, reportErrors); + } + return Ternary.False; + } if (source.flags & TypeFlags.TypeVariable) { if (source.flags & TypeFlags.IndexedAccess && target.flags & TypeFlags.IndexedAccess) { @@ -15727,6 +15783,9 @@ namespace ts { inferFromTypes((source).type, (target).type); contravariant = !contravariant; } + else if (source.flags & TypeFlags.StructuralTag && target.flags & TypeFlags.StructuralTag) { + inferFromTypes((source).type, (target).type); + } else if ((isLiteralType(source) || source.flags & TypeFlags.String) && target.flags & TypeFlags.Index) { const empty = createEmptyObjectTypeFromStringLiteral(source); contravariant = !contravariant; diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index d0d617b349531..7febcff6435f2 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -876,8 +876,8 @@ namespace ts { } export function createTypeOperatorNode(type: TypeNode): TypeOperatorNode; - export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; - export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | TypeNode, type?: TypeNode) { + export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.TagKeyword, type: TypeNode): TypeOperatorNode; + export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.TagKeyword | TypeNode, type?: TypeNode) { const node = createSynthesizedNode(SyntaxKind.TypeOperator) as TypeOperatorNode; node.operator = typeof operatorOrType === "number" ? operatorOrType : SyntaxKind.KeyOfKeyword; node.type = parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type! : operatorOrType); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index f1221883bde8c..a2e9c8c0c6012 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3053,6 +3053,7 @@ namespace ts { case SyntaxKind.ReadonlyKeyword: case SyntaxKind.SymbolKeyword: case SyntaxKind.UniqueKeyword: + case SyntaxKind.TagKeyword: case SyntaxKind.VoidKeyword: case SyntaxKind.UndefinedKeyword: case SyntaxKind.NullKeyword: @@ -3140,7 +3141,7 @@ namespace ts { return finishNode(postfix); } - function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) { + function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.TagKeyword) { const node = createNode(SyntaxKind.TypeOperator); parseExpected(operator); node.operator = operator; @@ -3163,6 +3164,7 @@ namespace ts { case SyntaxKind.KeyOfKeyword: case SyntaxKind.UniqueKeyword: case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.TagKeyword: return parseTypeOperator(operator); case SyntaxKind.InferKeyword: return parseInferType(); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index af9f565fb52ff..e10e42062baf3 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -138,6 +138,7 @@ namespace ts { async: SyntaxKind.AsyncKeyword, await: SyntaxKind.AwaitKeyword, of: SyntaxKind.OfKeyword, + tag: SyntaxKind.TagKeyword, }; const textToKeyword = createMapFromTemplate(textToKeywordObj); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 999a922041201..f6567ecf04106 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -103,6 +103,7 @@ namespace ts { | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword + | SyntaxKind.TagKeyword | SyntaxKind.OfKeyword; export type JsxTokenSyntaxKind = @@ -277,6 +278,7 @@ namespace ts { FromKeyword, GlobalKeyword, BigIntKeyword, + TagKeyword, OfKeyword, // LastKeyword and LastToken and LastContextualKeyword // Parse tree nodes @@ -1246,7 +1248,7 @@ namespace ts { export interface TypeOperatorNode extends TypeNode { kind: SyntaxKind.TypeOperator; - operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword; + operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.TagKeyword; type: TypeNode; } @@ -3984,6 +3986,7 @@ namespace ts { Conditional = 1 << 24, // T extends U ? X : Y Substitution = 1 << 25, // Type parameter substitution NonPrimitive = 1 << 26, // intrinsic object type + StructuralTag = 1 << 27, // tag T /* @internal */ AnyOrUnknown = Any | Unknown, @@ -4013,7 +4016,7 @@ namespace ts { UnionOrIntersection = Union | Intersection, StructuredType = Object | Union | Intersection, TypeVariable = TypeParameter | IndexedAccess, - InstantiableNonPrimitive = TypeVariable | Conditional | Substitution, + InstantiableNonPrimitive = TypeVariable | Conditional | Substitution | StructuralTag, InstantiablePrimitive = Index, Instantiable = InstantiableNonPrimitive | InstantiablePrimitive, StructuredOrInstantiable = StructuredType | Instantiable, @@ -4431,6 +4434,11 @@ namespace ts { substitute: Type; // Type to substitute for type parameter } + // Structual tag type, or a `tag T` (TypeFlags.StructuralTag) + export interface StructuralTagType extends InstantiableType { + type: Type; + } + /* @internal */ export const enum JsxReferenceKind { Component, diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 67d6a98e11ec5..a7da55b3368e5 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -73,7 +73,7 @@ declare namespace ts { end: number; } export type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind; - export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword; + export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.TagKeyword | SyntaxKind.OfKeyword; export type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; export enum SyntaxKind { Unknown = 0, @@ -225,179 +225,180 @@ declare namespace ts { FromKeyword = 145, GlobalKeyword = 146, BigIntKeyword = 147, - OfKeyword = 148, - QualifiedName = 149, - ComputedPropertyName = 150, - TypeParameter = 151, - Parameter = 152, - Decorator = 153, - PropertySignature = 154, - PropertyDeclaration = 155, - MethodSignature = 156, - MethodDeclaration = 157, - Constructor = 158, - GetAccessor = 159, - SetAccessor = 160, - CallSignature = 161, - ConstructSignature = 162, - IndexSignature = 163, - TypePredicate = 164, - TypeReference = 165, - FunctionType = 166, - ConstructorType = 167, - TypeQuery = 168, - TypeLiteral = 169, - ArrayType = 170, - TupleType = 171, - OptionalType = 172, - RestType = 173, - UnionType = 174, - IntersectionType = 175, - ConditionalType = 176, - InferType = 177, - ParenthesizedType = 178, - ThisType = 179, - TypeOperator = 180, - IndexedAccessType = 181, - MappedType = 182, - LiteralType = 183, - ImportType = 184, - ObjectBindingPattern = 185, - ArrayBindingPattern = 186, - BindingElement = 187, - ArrayLiteralExpression = 188, - ObjectLiteralExpression = 189, - PropertyAccessExpression = 190, - ElementAccessExpression = 191, - CallExpression = 192, - NewExpression = 193, - TaggedTemplateExpression = 194, - TypeAssertionExpression = 195, - ParenthesizedExpression = 196, - FunctionExpression = 197, - ArrowFunction = 198, - DeleteExpression = 199, - TypeOfExpression = 200, - VoidExpression = 201, - AwaitExpression = 202, - PrefixUnaryExpression = 203, - PostfixUnaryExpression = 204, - BinaryExpression = 205, - ConditionalExpression = 206, - TemplateExpression = 207, - YieldExpression = 208, - SpreadElement = 209, - ClassExpression = 210, - OmittedExpression = 211, - ExpressionWithTypeArguments = 212, - AsExpression = 213, - NonNullExpression = 214, - MetaProperty = 215, - SyntheticExpression = 216, - TemplateSpan = 217, - SemicolonClassElement = 218, - Block = 219, - VariableStatement = 220, - EmptyStatement = 221, - ExpressionStatement = 222, - IfStatement = 223, - DoStatement = 224, - WhileStatement = 225, - ForStatement = 226, - ForInStatement = 227, - ForOfStatement = 228, - ContinueStatement = 229, - BreakStatement = 230, - ReturnStatement = 231, - WithStatement = 232, - SwitchStatement = 233, - LabeledStatement = 234, - ThrowStatement = 235, - TryStatement = 236, - DebuggerStatement = 237, - VariableDeclaration = 238, - VariableDeclarationList = 239, - FunctionDeclaration = 240, - ClassDeclaration = 241, - InterfaceDeclaration = 242, - TypeAliasDeclaration = 243, - EnumDeclaration = 244, - ModuleDeclaration = 245, - ModuleBlock = 246, - CaseBlock = 247, - NamespaceExportDeclaration = 248, - ImportEqualsDeclaration = 249, - ImportDeclaration = 250, - ImportClause = 251, - NamespaceImport = 252, - NamedImports = 253, - ImportSpecifier = 254, - ExportAssignment = 255, - ExportDeclaration = 256, - NamedExports = 257, - ExportSpecifier = 258, - MissingDeclaration = 259, - ExternalModuleReference = 260, - JsxElement = 261, - JsxSelfClosingElement = 262, - JsxOpeningElement = 263, - JsxClosingElement = 264, - JsxFragment = 265, - JsxOpeningFragment = 266, - JsxClosingFragment = 267, - JsxAttribute = 268, - JsxAttributes = 269, - JsxSpreadAttribute = 270, - JsxExpression = 271, - CaseClause = 272, - DefaultClause = 273, - HeritageClause = 274, - CatchClause = 275, - PropertyAssignment = 276, - ShorthandPropertyAssignment = 277, - SpreadAssignment = 278, - EnumMember = 279, - UnparsedPrologue = 280, - UnparsedPrepend = 281, - UnparsedText = 282, - UnparsedInternalText = 283, - UnparsedSyntheticReference = 284, - SourceFile = 285, - Bundle = 286, - UnparsedSource = 287, - InputFiles = 288, - JSDocTypeExpression = 289, - JSDocAllType = 290, - JSDocUnknownType = 291, - JSDocNullableType = 292, - JSDocNonNullableType = 293, - JSDocOptionalType = 294, - JSDocFunctionType = 295, - JSDocVariadicType = 296, - JSDocNamepathType = 297, - JSDocComment = 298, - JSDocTypeLiteral = 299, - JSDocSignature = 300, - JSDocTag = 301, - JSDocAugmentsTag = 302, - JSDocAuthorTag = 303, - JSDocClassTag = 304, - JSDocCallbackTag = 305, - JSDocEnumTag = 306, - JSDocParameterTag = 307, - JSDocReturnTag = 308, - JSDocThisTag = 309, - JSDocTypeTag = 310, - JSDocTemplateTag = 311, - JSDocTypedefTag = 312, - JSDocPropertyTag = 313, - SyntaxList = 314, - NotEmittedStatement = 315, - PartiallyEmittedExpression = 316, - CommaListExpression = 317, - MergeDeclarationMarker = 318, - EndOfDeclarationMarker = 319, - Count = 320, + TagKeyword = 148, + OfKeyword = 149, + QualifiedName = 150, + ComputedPropertyName = 151, + TypeParameter = 152, + Parameter = 153, + Decorator = 154, + PropertySignature = 155, + PropertyDeclaration = 156, + MethodSignature = 157, + MethodDeclaration = 158, + Constructor = 159, + GetAccessor = 160, + SetAccessor = 161, + CallSignature = 162, + ConstructSignature = 163, + IndexSignature = 164, + TypePredicate = 165, + TypeReference = 166, + FunctionType = 167, + ConstructorType = 168, + TypeQuery = 169, + TypeLiteral = 170, + ArrayType = 171, + TupleType = 172, + OptionalType = 173, + RestType = 174, + UnionType = 175, + IntersectionType = 176, + ConditionalType = 177, + InferType = 178, + ParenthesizedType = 179, + ThisType = 180, + TypeOperator = 181, + IndexedAccessType = 182, + MappedType = 183, + LiteralType = 184, + ImportType = 185, + ObjectBindingPattern = 186, + ArrayBindingPattern = 187, + BindingElement = 188, + ArrayLiteralExpression = 189, + ObjectLiteralExpression = 190, + PropertyAccessExpression = 191, + ElementAccessExpression = 192, + CallExpression = 193, + NewExpression = 194, + TaggedTemplateExpression = 195, + TypeAssertionExpression = 196, + ParenthesizedExpression = 197, + FunctionExpression = 198, + ArrowFunction = 199, + DeleteExpression = 200, + TypeOfExpression = 201, + VoidExpression = 202, + AwaitExpression = 203, + PrefixUnaryExpression = 204, + PostfixUnaryExpression = 205, + BinaryExpression = 206, + ConditionalExpression = 207, + TemplateExpression = 208, + YieldExpression = 209, + SpreadElement = 210, + ClassExpression = 211, + OmittedExpression = 212, + ExpressionWithTypeArguments = 213, + AsExpression = 214, + NonNullExpression = 215, + MetaProperty = 216, + SyntheticExpression = 217, + TemplateSpan = 218, + SemicolonClassElement = 219, + Block = 220, + VariableStatement = 221, + EmptyStatement = 222, + ExpressionStatement = 223, + IfStatement = 224, + DoStatement = 225, + WhileStatement = 226, + ForStatement = 227, + ForInStatement = 228, + ForOfStatement = 229, + ContinueStatement = 230, + BreakStatement = 231, + ReturnStatement = 232, + WithStatement = 233, + SwitchStatement = 234, + LabeledStatement = 235, + ThrowStatement = 236, + TryStatement = 237, + DebuggerStatement = 238, + VariableDeclaration = 239, + VariableDeclarationList = 240, + FunctionDeclaration = 241, + ClassDeclaration = 242, + InterfaceDeclaration = 243, + TypeAliasDeclaration = 244, + EnumDeclaration = 245, + ModuleDeclaration = 246, + ModuleBlock = 247, + CaseBlock = 248, + NamespaceExportDeclaration = 249, + ImportEqualsDeclaration = 250, + ImportDeclaration = 251, + ImportClause = 252, + NamespaceImport = 253, + NamedImports = 254, + ImportSpecifier = 255, + ExportAssignment = 256, + ExportDeclaration = 257, + NamedExports = 258, + ExportSpecifier = 259, + MissingDeclaration = 260, + ExternalModuleReference = 261, + JsxElement = 262, + JsxSelfClosingElement = 263, + JsxOpeningElement = 264, + JsxClosingElement = 265, + JsxFragment = 266, + JsxOpeningFragment = 267, + JsxClosingFragment = 268, + JsxAttribute = 269, + JsxAttributes = 270, + JsxSpreadAttribute = 271, + JsxExpression = 272, + CaseClause = 273, + DefaultClause = 274, + HeritageClause = 275, + CatchClause = 276, + PropertyAssignment = 277, + ShorthandPropertyAssignment = 278, + SpreadAssignment = 279, + EnumMember = 280, + UnparsedPrologue = 281, + UnparsedPrepend = 282, + UnparsedText = 283, + UnparsedInternalText = 284, + UnparsedSyntheticReference = 285, + SourceFile = 286, + Bundle = 287, + UnparsedSource = 288, + InputFiles = 289, + JSDocTypeExpression = 290, + JSDocAllType = 291, + JSDocUnknownType = 292, + JSDocNullableType = 293, + JSDocNonNullableType = 294, + JSDocOptionalType = 295, + JSDocFunctionType = 296, + JSDocVariadicType = 297, + JSDocNamepathType = 298, + JSDocComment = 299, + JSDocTypeLiteral = 300, + JSDocSignature = 301, + JSDocTag = 302, + JSDocAugmentsTag = 303, + JSDocAuthorTag = 304, + JSDocClassTag = 305, + JSDocCallbackTag = 306, + JSDocEnumTag = 307, + JSDocParameterTag = 308, + JSDocReturnTag = 309, + JSDocThisTag = 310, + JSDocTypeTag = 311, + JSDocTemplateTag = 312, + JSDocTypedefTag = 313, + JSDocPropertyTag = 314, + SyntaxList = 315, + NotEmittedStatement = 316, + PartiallyEmittedExpression = 317, + CommaListExpression = 318, + MergeDeclarationMarker = 319, + EndOfDeclarationMarker = 320, + Count = 321, FirstAssignment = 60, LastAssignment = 72, FirstCompoundAssignment = 61, @@ -405,15 +406,15 @@ declare namespace ts { FirstReservedWord = 74, LastReservedWord = 109, FirstKeyword = 74, - LastKeyword = 148, + LastKeyword = 149, FirstFutureReservedWord = 110, LastFutureReservedWord = 118, - FirstTypeNode = 164, - LastTypeNode = 184, + FirstTypeNode = 165, + LastTypeNode = 185, FirstPunctuation = 18, LastPunctuation = 72, FirstToken = 0, - LastToken = 148, + LastToken = 149, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -422,11 +423,11 @@ declare namespace ts { LastTemplateToken = 17, FirstBinaryOperator = 28, LastBinaryOperator = 72, - FirstNode = 149, - FirstJSDocNode = 289, - LastJSDocNode = 313, - FirstJSDocTagNode = 301, - LastJSDocTagNode = 313, + FirstNode = 150, + FirstJSDocNode = 290, + LastJSDocNode = 314, + FirstJSDocTagNode = 302, + LastJSDocTagNode = 314, } export enum NodeFlags { None = 0, @@ -823,7 +824,7 @@ declare namespace ts { } export interface TypeOperatorNode extends TypeNode { kind: SyntaxKind.TypeOperator; - operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword; + operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.TagKeyword; type: TypeNode; } export interface IndexedAccessTypeNode extends TypeNode { @@ -2252,6 +2253,7 @@ declare namespace ts { Conditional = 16777216, Substitution = 33554432, NonPrimitive = 67108864, + StructuralTag = 134217728, Literal = 2944, Unit = 109440, StringOrNumberLiteral = 384, @@ -2266,11 +2268,11 @@ declare namespace ts { UnionOrIntersection = 3145728, StructuredType = 3670016, TypeVariable = 8650752, - InstantiableNonPrimitive = 58982400, + InstantiableNonPrimitive = 193200128, InstantiablePrimitive = 4194304, - Instantiable = 63176704, - StructuredOrInstantiable = 66846720, - Narrowable = 133970943, + Instantiable = 197394432, + StructuredOrInstantiable = 201064448, + Narrowable = 268188671, NotUnionOrUnit = 67637251, } export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; @@ -2415,6 +2417,9 @@ declare namespace ts { typeVariable: TypeVariable; substitute: Type; } + export interface StructuralTagType extends InstantiableType { + type: Type; + } export enum SignatureKind { Call = 0, Construct = 1 @@ -3870,7 +3875,7 @@ declare namespace ts { function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode; function createThisTypeNode(): ThisTypeNode; function createTypeOperatorNode(type: TypeNode): TypeOperatorNode; - function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.TagKeyword, type: TypeNode): TypeOperatorNode; function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 279357eddf752..a563f2fab4a21 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -73,7 +73,7 @@ declare namespace ts { end: number; } export type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind; - export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword; + export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.TagKeyword | SyntaxKind.OfKeyword; export type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; export enum SyntaxKind { Unknown = 0, @@ -225,179 +225,180 @@ declare namespace ts { FromKeyword = 145, GlobalKeyword = 146, BigIntKeyword = 147, - OfKeyword = 148, - QualifiedName = 149, - ComputedPropertyName = 150, - TypeParameter = 151, - Parameter = 152, - Decorator = 153, - PropertySignature = 154, - PropertyDeclaration = 155, - MethodSignature = 156, - MethodDeclaration = 157, - Constructor = 158, - GetAccessor = 159, - SetAccessor = 160, - CallSignature = 161, - ConstructSignature = 162, - IndexSignature = 163, - TypePredicate = 164, - TypeReference = 165, - FunctionType = 166, - ConstructorType = 167, - TypeQuery = 168, - TypeLiteral = 169, - ArrayType = 170, - TupleType = 171, - OptionalType = 172, - RestType = 173, - UnionType = 174, - IntersectionType = 175, - ConditionalType = 176, - InferType = 177, - ParenthesizedType = 178, - ThisType = 179, - TypeOperator = 180, - IndexedAccessType = 181, - MappedType = 182, - LiteralType = 183, - ImportType = 184, - ObjectBindingPattern = 185, - ArrayBindingPattern = 186, - BindingElement = 187, - ArrayLiteralExpression = 188, - ObjectLiteralExpression = 189, - PropertyAccessExpression = 190, - ElementAccessExpression = 191, - CallExpression = 192, - NewExpression = 193, - TaggedTemplateExpression = 194, - TypeAssertionExpression = 195, - ParenthesizedExpression = 196, - FunctionExpression = 197, - ArrowFunction = 198, - DeleteExpression = 199, - TypeOfExpression = 200, - VoidExpression = 201, - AwaitExpression = 202, - PrefixUnaryExpression = 203, - PostfixUnaryExpression = 204, - BinaryExpression = 205, - ConditionalExpression = 206, - TemplateExpression = 207, - YieldExpression = 208, - SpreadElement = 209, - ClassExpression = 210, - OmittedExpression = 211, - ExpressionWithTypeArguments = 212, - AsExpression = 213, - NonNullExpression = 214, - MetaProperty = 215, - SyntheticExpression = 216, - TemplateSpan = 217, - SemicolonClassElement = 218, - Block = 219, - VariableStatement = 220, - EmptyStatement = 221, - ExpressionStatement = 222, - IfStatement = 223, - DoStatement = 224, - WhileStatement = 225, - ForStatement = 226, - ForInStatement = 227, - ForOfStatement = 228, - ContinueStatement = 229, - BreakStatement = 230, - ReturnStatement = 231, - WithStatement = 232, - SwitchStatement = 233, - LabeledStatement = 234, - ThrowStatement = 235, - TryStatement = 236, - DebuggerStatement = 237, - VariableDeclaration = 238, - VariableDeclarationList = 239, - FunctionDeclaration = 240, - ClassDeclaration = 241, - InterfaceDeclaration = 242, - TypeAliasDeclaration = 243, - EnumDeclaration = 244, - ModuleDeclaration = 245, - ModuleBlock = 246, - CaseBlock = 247, - NamespaceExportDeclaration = 248, - ImportEqualsDeclaration = 249, - ImportDeclaration = 250, - ImportClause = 251, - NamespaceImport = 252, - NamedImports = 253, - ImportSpecifier = 254, - ExportAssignment = 255, - ExportDeclaration = 256, - NamedExports = 257, - ExportSpecifier = 258, - MissingDeclaration = 259, - ExternalModuleReference = 260, - JsxElement = 261, - JsxSelfClosingElement = 262, - JsxOpeningElement = 263, - JsxClosingElement = 264, - JsxFragment = 265, - JsxOpeningFragment = 266, - JsxClosingFragment = 267, - JsxAttribute = 268, - JsxAttributes = 269, - JsxSpreadAttribute = 270, - JsxExpression = 271, - CaseClause = 272, - DefaultClause = 273, - HeritageClause = 274, - CatchClause = 275, - PropertyAssignment = 276, - ShorthandPropertyAssignment = 277, - SpreadAssignment = 278, - EnumMember = 279, - UnparsedPrologue = 280, - UnparsedPrepend = 281, - UnparsedText = 282, - UnparsedInternalText = 283, - UnparsedSyntheticReference = 284, - SourceFile = 285, - Bundle = 286, - UnparsedSource = 287, - InputFiles = 288, - JSDocTypeExpression = 289, - JSDocAllType = 290, - JSDocUnknownType = 291, - JSDocNullableType = 292, - JSDocNonNullableType = 293, - JSDocOptionalType = 294, - JSDocFunctionType = 295, - JSDocVariadicType = 296, - JSDocNamepathType = 297, - JSDocComment = 298, - JSDocTypeLiteral = 299, - JSDocSignature = 300, - JSDocTag = 301, - JSDocAugmentsTag = 302, - JSDocAuthorTag = 303, - JSDocClassTag = 304, - JSDocCallbackTag = 305, - JSDocEnumTag = 306, - JSDocParameterTag = 307, - JSDocReturnTag = 308, - JSDocThisTag = 309, - JSDocTypeTag = 310, - JSDocTemplateTag = 311, - JSDocTypedefTag = 312, - JSDocPropertyTag = 313, - SyntaxList = 314, - NotEmittedStatement = 315, - PartiallyEmittedExpression = 316, - CommaListExpression = 317, - MergeDeclarationMarker = 318, - EndOfDeclarationMarker = 319, - Count = 320, + TagKeyword = 148, + OfKeyword = 149, + QualifiedName = 150, + ComputedPropertyName = 151, + TypeParameter = 152, + Parameter = 153, + Decorator = 154, + PropertySignature = 155, + PropertyDeclaration = 156, + MethodSignature = 157, + MethodDeclaration = 158, + Constructor = 159, + GetAccessor = 160, + SetAccessor = 161, + CallSignature = 162, + ConstructSignature = 163, + IndexSignature = 164, + TypePredicate = 165, + TypeReference = 166, + FunctionType = 167, + ConstructorType = 168, + TypeQuery = 169, + TypeLiteral = 170, + ArrayType = 171, + TupleType = 172, + OptionalType = 173, + RestType = 174, + UnionType = 175, + IntersectionType = 176, + ConditionalType = 177, + InferType = 178, + ParenthesizedType = 179, + ThisType = 180, + TypeOperator = 181, + IndexedAccessType = 182, + MappedType = 183, + LiteralType = 184, + ImportType = 185, + ObjectBindingPattern = 186, + ArrayBindingPattern = 187, + BindingElement = 188, + ArrayLiteralExpression = 189, + ObjectLiteralExpression = 190, + PropertyAccessExpression = 191, + ElementAccessExpression = 192, + CallExpression = 193, + NewExpression = 194, + TaggedTemplateExpression = 195, + TypeAssertionExpression = 196, + ParenthesizedExpression = 197, + FunctionExpression = 198, + ArrowFunction = 199, + DeleteExpression = 200, + TypeOfExpression = 201, + VoidExpression = 202, + AwaitExpression = 203, + PrefixUnaryExpression = 204, + PostfixUnaryExpression = 205, + BinaryExpression = 206, + ConditionalExpression = 207, + TemplateExpression = 208, + YieldExpression = 209, + SpreadElement = 210, + ClassExpression = 211, + OmittedExpression = 212, + ExpressionWithTypeArguments = 213, + AsExpression = 214, + NonNullExpression = 215, + MetaProperty = 216, + SyntheticExpression = 217, + TemplateSpan = 218, + SemicolonClassElement = 219, + Block = 220, + VariableStatement = 221, + EmptyStatement = 222, + ExpressionStatement = 223, + IfStatement = 224, + DoStatement = 225, + WhileStatement = 226, + ForStatement = 227, + ForInStatement = 228, + ForOfStatement = 229, + ContinueStatement = 230, + BreakStatement = 231, + ReturnStatement = 232, + WithStatement = 233, + SwitchStatement = 234, + LabeledStatement = 235, + ThrowStatement = 236, + TryStatement = 237, + DebuggerStatement = 238, + VariableDeclaration = 239, + VariableDeclarationList = 240, + FunctionDeclaration = 241, + ClassDeclaration = 242, + InterfaceDeclaration = 243, + TypeAliasDeclaration = 244, + EnumDeclaration = 245, + ModuleDeclaration = 246, + ModuleBlock = 247, + CaseBlock = 248, + NamespaceExportDeclaration = 249, + ImportEqualsDeclaration = 250, + ImportDeclaration = 251, + ImportClause = 252, + NamespaceImport = 253, + NamedImports = 254, + ImportSpecifier = 255, + ExportAssignment = 256, + ExportDeclaration = 257, + NamedExports = 258, + ExportSpecifier = 259, + MissingDeclaration = 260, + ExternalModuleReference = 261, + JsxElement = 262, + JsxSelfClosingElement = 263, + JsxOpeningElement = 264, + JsxClosingElement = 265, + JsxFragment = 266, + JsxOpeningFragment = 267, + JsxClosingFragment = 268, + JsxAttribute = 269, + JsxAttributes = 270, + JsxSpreadAttribute = 271, + JsxExpression = 272, + CaseClause = 273, + DefaultClause = 274, + HeritageClause = 275, + CatchClause = 276, + PropertyAssignment = 277, + ShorthandPropertyAssignment = 278, + SpreadAssignment = 279, + EnumMember = 280, + UnparsedPrologue = 281, + UnparsedPrepend = 282, + UnparsedText = 283, + UnparsedInternalText = 284, + UnparsedSyntheticReference = 285, + SourceFile = 286, + Bundle = 287, + UnparsedSource = 288, + InputFiles = 289, + JSDocTypeExpression = 290, + JSDocAllType = 291, + JSDocUnknownType = 292, + JSDocNullableType = 293, + JSDocNonNullableType = 294, + JSDocOptionalType = 295, + JSDocFunctionType = 296, + JSDocVariadicType = 297, + JSDocNamepathType = 298, + JSDocComment = 299, + JSDocTypeLiteral = 300, + JSDocSignature = 301, + JSDocTag = 302, + JSDocAugmentsTag = 303, + JSDocAuthorTag = 304, + JSDocClassTag = 305, + JSDocCallbackTag = 306, + JSDocEnumTag = 307, + JSDocParameterTag = 308, + JSDocReturnTag = 309, + JSDocThisTag = 310, + JSDocTypeTag = 311, + JSDocTemplateTag = 312, + JSDocTypedefTag = 313, + JSDocPropertyTag = 314, + SyntaxList = 315, + NotEmittedStatement = 316, + PartiallyEmittedExpression = 317, + CommaListExpression = 318, + MergeDeclarationMarker = 319, + EndOfDeclarationMarker = 320, + Count = 321, FirstAssignment = 60, LastAssignment = 72, FirstCompoundAssignment = 61, @@ -405,15 +406,15 @@ declare namespace ts { FirstReservedWord = 74, LastReservedWord = 109, FirstKeyword = 74, - LastKeyword = 148, + LastKeyword = 149, FirstFutureReservedWord = 110, LastFutureReservedWord = 118, - FirstTypeNode = 164, - LastTypeNode = 184, + FirstTypeNode = 165, + LastTypeNode = 185, FirstPunctuation = 18, LastPunctuation = 72, FirstToken = 0, - LastToken = 148, + LastToken = 149, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -422,11 +423,11 @@ declare namespace ts { LastTemplateToken = 17, FirstBinaryOperator = 28, LastBinaryOperator = 72, - FirstNode = 149, - FirstJSDocNode = 289, - LastJSDocNode = 313, - FirstJSDocTagNode = 301, - LastJSDocTagNode = 313, + FirstNode = 150, + FirstJSDocNode = 290, + LastJSDocNode = 314, + FirstJSDocTagNode = 302, + LastJSDocTagNode = 314, } export enum NodeFlags { None = 0, @@ -823,7 +824,7 @@ declare namespace ts { } export interface TypeOperatorNode extends TypeNode { kind: SyntaxKind.TypeOperator; - operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword; + operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.TagKeyword; type: TypeNode; } export interface IndexedAccessTypeNode extends TypeNode { @@ -2252,6 +2253,7 @@ declare namespace ts { Conditional = 16777216, Substitution = 33554432, NonPrimitive = 67108864, + StructuralTag = 134217728, Literal = 2944, Unit = 109440, StringOrNumberLiteral = 384, @@ -2266,11 +2268,11 @@ declare namespace ts { UnionOrIntersection = 3145728, StructuredType = 3670016, TypeVariable = 8650752, - InstantiableNonPrimitive = 58982400, + InstantiableNonPrimitive = 193200128, InstantiablePrimitive = 4194304, - Instantiable = 63176704, - StructuredOrInstantiable = 66846720, - Narrowable = 133970943, + Instantiable = 197394432, + StructuredOrInstantiable = 201064448, + Narrowable = 268188671, NotUnionOrUnit = 67637251, } export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; @@ -2415,6 +2417,9 @@ declare namespace ts { typeVariable: TypeVariable; substitute: Type; } + export interface StructuralTagType extends InstantiableType { + type: Type; + } export enum SignatureKind { Call = 0, Construct = 1 @@ -3870,7 +3875,7 @@ declare namespace ts { function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode; function createThisTypeNode(): ThisTypeNode; function createTypeOperatorNode(type: TypeNode): TypeOperatorNode; - function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.TagKeyword, type: TypeNode): TypeOperatorNode; function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; diff --git a/tests/baselines/reference/structuralTagTypes.js b/tests/baselines/reference/structuralTagTypes.js new file mode 100644 index 0000000000000..6eb7e2e5c5484 --- /dev/null +++ b/tests/baselines/reference/structuralTagTypes.js @@ -0,0 +1,139 @@ +//// [structuralTagTypes.ts] +export type Downcased = string & tag { downcased: void; }; +export type Analyzed = T & tag { analyzed: void; }; +export type Paired = { + x: number & tag {x: number;}; + y: number & tag {y: number;}; +}; + +export function downcase(x: string): Downcased { + return x.toLocaleLowerCase() as Downcased; +} + +export function downcaseLit(x: T): T & Downcased { + return x.toLocaleLowerCase() as T & Downcased; +} + +export function isDowncase(x: string): x is Downcased { + return null as any; +} + +export function analyze(x: T): Analyzed { + return x as Analyzed; +} + +export function isAnalyzed(x: T): x is Analyzed { + return Math.random() > 0.33 ? false : true; +} + +export function isPaired(x: {x: number, y: number}): x is Paired { + return true; +} + +export function makePair(x: number, y: number): Paired { + return {x, y} as Paired; +} + +const a = "ok"; +export const b = downcase(a); +export const d = downcaseLit(b); + +if (isDowncase(d)) { + d; +} + +const e = {data: { value: "str" }}; +export const f = analyze(e); +if (isAnalyzed(e)) { + e; +} + +export const g = makePair(0, 0); +const h = {x: 0, y: 0}; +if (isPaired(h)) { + h; +} + + +//// [structuralTagTypes.js] +"use strict"; +exports.__esModule = true; +function downcase(x) { + return x.toLocaleLowerCase(); +} +exports.downcase = downcase; +function downcaseLit(x) { + return x.toLocaleLowerCase(); +} +exports.downcaseLit = downcaseLit; +function isDowncase(x) { + return null; +} +exports.isDowncase = isDowncase; +function analyze(x) { + return x; +} +exports.analyze = analyze; +function isAnalyzed(x) { + return Math.random() > 0.33 ? false : true; +} +exports.isAnalyzed = isAnalyzed; +function isPaired(x) { + return true; +} +exports.isPaired = isPaired; +function makePair(x, y) { + return { x: x, y: y }; +} +exports.makePair = makePair; +var a = "ok"; +exports.b = downcase(a); +exports.d = downcaseLit(exports.b); +if (isDowncase(exports.d)) { + exports.d; +} +var e = { data: { value: "str" } }; +exports.f = analyze(e); +if (isAnalyzed(e)) { + e; +} +exports.g = makePair(0, 0); +var h = { x: 0, y: 0 }; +if (isPaired(h)) { + h; +} + + +//// [structuralTagTypes.d.ts] +export declare type Downcased = string & tag { + downcased: void; +}; +export declare type Analyzed = T & tag { + analyzed: void; +}; +export declare type Paired = { + x: number & tag { + x: number; + }; + y: number & tag { + y: number; + }; +}; +export declare function downcase(x: string): Downcased; +export declare function downcaseLit(x: T): T & Downcased; +export declare function isDowncase(x: string): x is Downcased; +export declare function analyze(x: T): Analyzed; +export declare function isAnalyzed(x: T): x is Analyzed; +export declare function isPaired(x: { + x: number; + y: number; +}): x is Paired; +export declare function makePair(x: number, y: number): Paired; +export declare const b: Downcased; +export declare const d: Downcased; +export declare const f: Analyzed<{ + data: { + value: string; + }; +}>; +export declare const g: Paired; diff --git a/tests/baselines/reference/structuralTagTypes.symbols b/tests/baselines/reference/structuralTagTypes.symbols new file mode 100644 index 0000000000000..ddea35d683bec --- /dev/null +++ b/tests/baselines/reference/structuralTagTypes.symbols @@ -0,0 +1,169 @@ +=== tests/cases/conformance/types/structuralTags/structuralTagTypes.ts === +export type Downcased = string & tag { downcased: void; }; +>Downcased : Symbol(Downcased, Decl(structuralTagTypes.ts, 0, 0)) +>downcased : Symbol(downcased, Decl(structuralTagTypes.ts, 0, 38)) + +export type Analyzed = T & tag { analyzed: void; }; +>Analyzed : Symbol(Analyzed, Decl(structuralTagTypes.ts, 0, 58)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 1, 21)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 1, 21)) +>analyzed : Symbol(analyzed, Decl(structuralTagTypes.ts, 1, 35)) + +export type Paired = { +>Paired : Symbol(Paired, Decl(structuralTagTypes.ts, 1, 54)) + + x: number & tag {x: number;}; +>x : Symbol(x, Decl(structuralTagTypes.ts, 2, 22)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 3, 21)) + + y: number & tag {y: number;}; +>y : Symbol(y, Decl(structuralTagTypes.ts, 3, 33)) +>y : Symbol(y, Decl(structuralTagTypes.ts, 4, 21)) + +}; + +export function downcase(x: string): Downcased { +>downcase : Symbol(downcase, Decl(structuralTagTypes.ts, 5, 2)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 7, 25)) +>Downcased : Symbol(Downcased, Decl(structuralTagTypes.ts, 0, 0)) + + return x.toLocaleLowerCase() as Downcased; +>x.toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 7, 25)) +>toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --)) +>Downcased : Symbol(Downcased, Decl(structuralTagTypes.ts, 0, 0)) +} + +export function downcaseLit(x: T): T & Downcased { +>downcaseLit : Symbol(downcaseLit, Decl(structuralTagTypes.ts, 9, 1)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 11, 28)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 11, 46)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 11, 28)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 11, 28)) +>Downcased : Symbol(Downcased, Decl(structuralTagTypes.ts, 0, 0)) + + return x.toLocaleLowerCase() as T & Downcased; +>x.toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 11, 46)) +>toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 11, 28)) +>Downcased : Symbol(Downcased, Decl(structuralTagTypes.ts, 0, 0)) +} + +export function isDowncase(x: string): x is Downcased { +>isDowncase : Symbol(isDowncase, Decl(structuralTagTypes.ts, 13, 1)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 15, 27)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 15, 27)) +>Downcased : Symbol(Downcased, Decl(structuralTagTypes.ts, 0, 0)) + + return null as any; +} + +export function analyze(x: T): Analyzed { +>analyze : Symbol(analyze, Decl(structuralTagTypes.ts, 17, 1)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 19, 24)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 19, 27)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 19, 24)) +>Analyzed : Symbol(Analyzed, Decl(structuralTagTypes.ts, 0, 58)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 19, 24)) + + return x as Analyzed; +>x : Symbol(x, Decl(structuralTagTypes.ts, 19, 27)) +>Analyzed : Symbol(Analyzed, Decl(structuralTagTypes.ts, 0, 58)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 19, 24)) +} + +export function isAnalyzed(x: T): x is Analyzed { +>isAnalyzed : Symbol(isAnalyzed, Decl(structuralTagTypes.ts, 21, 1)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 23, 27)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 23, 30)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 23, 27)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 23, 30)) +>Analyzed : Symbol(Analyzed, Decl(structuralTagTypes.ts, 0, 58)) +>T : Symbol(T, Decl(structuralTagTypes.ts, 23, 27)) + + return Math.random() > 0.33 ? false : true; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +} + +export function isPaired(x: {x: number, y: number}): x is Paired { +>isPaired : Symbol(isPaired, Decl(structuralTagTypes.ts, 25, 1)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 27, 25)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 27, 29)) +>y : Symbol(y, Decl(structuralTagTypes.ts, 27, 39)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 27, 25)) +>Paired : Symbol(Paired, Decl(structuralTagTypes.ts, 1, 54)) + + return true; +} + +export function makePair(x: number, y: number): Paired { +>makePair : Symbol(makePair, Decl(structuralTagTypes.ts, 29, 1)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 31, 25)) +>y : Symbol(y, Decl(structuralTagTypes.ts, 31, 35)) +>Paired : Symbol(Paired, Decl(structuralTagTypes.ts, 1, 54)) + + return {x, y} as Paired; +>x : Symbol(x, Decl(structuralTagTypes.ts, 32, 12)) +>y : Symbol(y, Decl(structuralTagTypes.ts, 32, 14)) +>Paired : Symbol(Paired, Decl(structuralTagTypes.ts, 1, 54)) +} + +const a = "ok"; +>a : Symbol(a, Decl(structuralTagTypes.ts, 35, 5)) + +export const b = downcase(a); +>b : Symbol(b, Decl(structuralTagTypes.ts, 36, 12)) +>downcase : Symbol(downcase, Decl(structuralTagTypes.ts, 5, 2)) +>a : Symbol(a, Decl(structuralTagTypes.ts, 35, 5)) + +export const d = downcaseLit(b); +>d : Symbol(d, Decl(structuralTagTypes.ts, 37, 12)) +>downcaseLit : Symbol(downcaseLit, Decl(structuralTagTypes.ts, 9, 1)) +>b : Symbol(b, Decl(structuralTagTypes.ts, 36, 12)) + +if (isDowncase(d)) { +>isDowncase : Symbol(isDowncase, Decl(structuralTagTypes.ts, 13, 1)) +>d : Symbol(d, Decl(structuralTagTypes.ts, 37, 12)) + + d; +>d : Symbol(d, Decl(structuralTagTypes.ts, 37, 12)) +} + +const e = {data: { value: "str" }}; +>e : Symbol(e, Decl(structuralTagTypes.ts, 43, 5)) +>data : Symbol(data, Decl(structuralTagTypes.ts, 43, 11)) +>value : Symbol(value, Decl(structuralTagTypes.ts, 43, 18)) + +export const f = analyze(e); +>f : Symbol(f, Decl(structuralTagTypes.ts, 44, 12)) +>analyze : Symbol(analyze, Decl(structuralTagTypes.ts, 17, 1)) +>e : Symbol(e, Decl(structuralTagTypes.ts, 43, 5)) + +if (isAnalyzed(e)) { +>isAnalyzed : Symbol(isAnalyzed, Decl(structuralTagTypes.ts, 21, 1)) +>e : Symbol(e, Decl(structuralTagTypes.ts, 43, 5)) + + e; +>e : Symbol(e, Decl(structuralTagTypes.ts, 43, 5)) +} + +export const g = makePair(0, 0); +>g : Symbol(g, Decl(structuralTagTypes.ts, 49, 12)) +>makePair : Symbol(makePair, Decl(structuralTagTypes.ts, 29, 1)) + +const h = {x: 0, y: 0}; +>h : Symbol(h, Decl(structuralTagTypes.ts, 50, 5)) +>x : Symbol(x, Decl(structuralTagTypes.ts, 50, 11)) +>y : Symbol(y, Decl(structuralTagTypes.ts, 50, 16)) + +if (isPaired(h)) { +>isPaired : Symbol(isPaired, Decl(structuralTagTypes.ts, 25, 1)) +>h : Symbol(h, Decl(structuralTagTypes.ts, 50, 5)) + + h; +>h : Symbol(h, Decl(structuralTagTypes.ts, 50, 5)) +} + diff --git a/tests/baselines/reference/structuralTagTypes.types b/tests/baselines/reference/structuralTagTypes.types new file mode 100644 index 0000000000000..870c78d1f4730 --- /dev/null +++ b/tests/baselines/reference/structuralTagTypes.types @@ -0,0 +1,174 @@ +=== tests/cases/conformance/types/structuralTags/structuralTagTypes.ts === +export type Downcased = string & tag { downcased: void; }; +>Downcased : Downcased +>downcased : void + +export type Analyzed = T & tag { analyzed: void; }; +>Analyzed : Analyzed +>analyzed : void + +export type Paired = { +>Paired : Paired + + x: number & tag {x: number;}; +>x : number & tag { x: number; } +>x : number + + y: number & tag {y: number;}; +>y : number & tag { y: number; } +>y : number + +}; + +export function downcase(x: string): Downcased { +>downcase : (x: string) => Downcased +>x : string + + return x.toLocaleLowerCase() as Downcased; +>x.toLocaleLowerCase() as Downcased : Downcased +>x.toLocaleLowerCase() : string +>x.toLocaleLowerCase : (locales?: string | string[]) => string +>x : string +>toLocaleLowerCase : (locales?: string | string[]) => string +} + +export function downcaseLit(x: T): T & Downcased { +>downcaseLit : (x: T) => T & string & tag { downcased: void; } +>x : T + + return x.toLocaleLowerCase() as T & Downcased; +>x.toLocaleLowerCase() as T & Downcased : T & string & tag { downcased: void; } +>x.toLocaleLowerCase() : string +>x.toLocaleLowerCase : (locales?: string | string[]) => string +>x : T +>toLocaleLowerCase : (locales?: string | string[]) => string +} + +export function isDowncase(x: string): x is Downcased { +>isDowncase : (x: string) => x is Downcased +>x : string + + return null as any; +>null as any : any +>null : null +} + +export function analyze(x: T): Analyzed { +>analyze : (x: T) => Analyzed +>x : T + + return x as Analyzed; +>x as Analyzed : Analyzed +>x : T +} + +export function isAnalyzed(x: T): x is Analyzed { +>isAnalyzed : (x: T) => x is Analyzed +>x : T + + return Math.random() > 0.33 ? false : true; +>Math.random() > 0.33 ? false : true : boolean +>Math.random() > 0.33 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.33 : 0.33 +>false : false +>true : true +} + +export function isPaired(x: {x: number, y: number}): x is Paired { +>isPaired : (x: { x: number; y: number; }) => x is Paired +>x : { x: number; y: number; } +>x : number +>y : number + + return true; +>true : true +} + +export function makePair(x: number, y: number): Paired { +>makePair : (x: number, y: number) => Paired +>x : number +>y : number + + return {x, y} as Paired; +>{x, y} as Paired : Paired +>{x, y} : { x: number; y: number; } +>x : number +>y : number +} + +const a = "ok"; +>a : "ok" +>"ok" : "ok" + +export const b = downcase(a); +>b : Downcased +>downcase(a) : Downcased +>downcase : (x: string) => Downcased +>a : "ok" + +export const d = downcaseLit(b); +>d : Downcased +>downcaseLit(b) : Downcased +>downcaseLit : (x: T) => T & string & tag { downcased: void; } +>b : Downcased + +if (isDowncase(d)) { +>isDowncase(d) : boolean +>isDowncase : (x: string) => x is Downcased +>d : Downcased + + d; +>d : Downcased +} + +const e = {data: { value: "str" }}; +>e : { data: { value: string; }; } +>{data: { value: "str" }} : { data: { value: string; }; } +>data : { value: string; } +>{ value: "str" } : { value: string; } +>value : string +>"str" : "str" + +export const f = analyze(e); +>f : Analyzed<{ data: { value: string; }; }> +>analyze(e) : Analyzed<{ data: { value: string; }; }> +>analyze : (x: T) => Analyzed +>e : { data: { value: string; }; } + +if (isAnalyzed(e)) { +>isAnalyzed(e) : boolean +>isAnalyzed : (x: T) => x is Analyzed +>e : { data: { value: string; }; } + + e; +>e : Analyzed<{ data: { value: string; }; }> +} + +export const g = makePair(0, 0); +>g : Paired +>makePair(0, 0) : Paired +>makePair : (x: number, y: number) => Paired +>0 : 0 +>0 : 0 + +const h = {x: 0, y: 0}; +>h : { x: number; y: number; } +>{x: 0, y: 0} : { x: number; y: number; } +>x : number +>0 : 0 +>y : number +>0 : 0 + +if (isPaired(h)) { +>isPaired(h) : boolean +>isPaired : (x: { x: number; y: number; }) => x is Paired +>h : { x: number; y: number; } + + h; +>h : Paired +} + diff --git a/tests/baselines/reference/structuralTagTypes1.js b/tests/baselines/reference/structuralTagTypes1.js new file mode 100644 index 0000000000000..796e89765f3c4 --- /dev/null +++ b/tests/baselines/reference/structuralTagTypes1.js @@ -0,0 +1,53 @@ +//// [structuralTagTypes1.ts] +export type Paired = { + x: number & tag {x}; + y: number & tag {y}; +}; + + +export function isPaired(x: {x: number, y: number}): x is Paired { + return true; +} + +export function makePair(x: number, y: number): Paired { + return {x, y} as Paired; +} + +const a = makePair(0, 0); +const b = {x: 0, y: 0}; + +if (Math.random() > 0.3) { + b.x = a.x; + b.y = a.y; +} + +if (isPaired(b)) { + b.x = a.x; + b.y = a.y; + a.x = b.x; + a.y = b.y; +} + +//// [structuralTagTypes1.js] +"use strict"; +exports.__esModule = true; +function isPaired(x) { + return true; +} +exports.isPaired = isPaired; +function makePair(x, y) { + return { x: x, y: y }; +} +exports.makePair = makePair; +var a = makePair(0, 0); +var b = { x: 0, y: 0 }; +if (Math.random() > 0.3) { + b.x = a.x; + b.y = a.y; +} +if (isPaired(b)) { + b.x = a.x; + b.y = a.y; + a.x = b.x; + a.y = b.y; +} diff --git a/tests/baselines/reference/structuralTagTypes1.symbols b/tests/baselines/reference/structuralTagTypes1.symbols new file mode 100644 index 0000000000000..7c0961b0e4dc4 --- /dev/null +++ b/tests/baselines/reference/structuralTagTypes1.symbols @@ -0,0 +1,105 @@ +=== tests/cases/conformance/types/structuralTags/structuralTagTypes1.ts === +export type Paired = { +>Paired : Symbol(Paired, Decl(structuralTagTypes1.ts, 0, 0)) + + x: number & tag {x}; +>x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 1, 21)) + + y: number & tag {y}; +>y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 2, 21)) + +}; + + +export function isPaired(x: {x: number, y: number}): x is Paired { +>isPaired : Symbol(isPaired, Decl(structuralTagTypes1.ts, 3, 2)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 6, 25)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 6, 29)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 6, 39)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 6, 25)) +>Paired : Symbol(Paired, Decl(structuralTagTypes1.ts, 0, 0)) + + return true; +} + +export function makePair(x: number, y: number): Paired { +>makePair : Symbol(makePair, Decl(structuralTagTypes1.ts, 8, 1)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 10, 25)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 10, 35)) +>Paired : Symbol(Paired, Decl(structuralTagTypes1.ts, 0, 0)) + + return {x, y} as Paired; +>x : Symbol(x, Decl(structuralTagTypes1.ts, 11, 12)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 11, 14)) +>Paired : Symbol(Paired, Decl(structuralTagTypes1.ts, 0, 0)) +} + +const a = makePair(0, 0); +>a : Symbol(a, Decl(structuralTagTypes1.ts, 14, 5)) +>makePair : Symbol(makePair, Decl(structuralTagTypes1.ts, 8, 1)) + +const b = {x: 0, y: 0}; +>b : Symbol(b, Decl(structuralTagTypes1.ts, 15, 5)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 15, 11)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 15, 16)) + +if (Math.random() > 0.3) { +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + b.x = a.x; +>b.x : Symbol(x, Decl(structuralTagTypes1.ts, 15, 11)) +>b : Symbol(b, Decl(structuralTagTypes1.ts, 15, 5)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 15, 11)) +>a.x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) +>a : Symbol(a, Decl(structuralTagTypes1.ts, 14, 5)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) + + b.y = a.y; +>b.y : Symbol(y, Decl(structuralTagTypes1.ts, 15, 16)) +>b : Symbol(b, Decl(structuralTagTypes1.ts, 15, 5)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 15, 16)) +>a.y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) +>a : Symbol(a, Decl(structuralTagTypes1.ts, 14, 5)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) +} + +if (isPaired(b)) { +>isPaired : Symbol(isPaired, Decl(structuralTagTypes1.ts, 3, 2)) +>b : Symbol(b, Decl(structuralTagTypes1.ts, 15, 5)) + + b.x = a.x; +>b.x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) +>b : Symbol(b, Decl(structuralTagTypes1.ts, 15, 5)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) +>a.x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) +>a : Symbol(a, Decl(structuralTagTypes1.ts, 14, 5)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) + + b.y = a.y; +>b.y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) +>b : Symbol(b, Decl(structuralTagTypes1.ts, 15, 5)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) +>a.y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) +>a : Symbol(a, Decl(structuralTagTypes1.ts, 14, 5)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) + + a.x = b.x; +>a.x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) +>a : Symbol(a, Decl(structuralTagTypes1.ts, 14, 5)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) +>b.x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) +>b : Symbol(b, Decl(structuralTagTypes1.ts, 15, 5)) +>x : Symbol(x, Decl(structuralTagTypes1.ts, 0, 22)) + + a.y = b.y; +>a.y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) +>a : Symbol(a, Decl(structuralTagTypes1.ts, 14, 5)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) +>b.y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) +>b : Symbol(b, Decl(structuralTagTypes1.ts, 15, 5)) +>y : Symbol(y, Decl(structuralTagTypes1.ts, 1, 24)) +} diff --git a/tests/baselines/reference/structuralTagTypes1.types b/tests/baselines/reference/structuralTagTypes1.types new file mode 100644 index 0000000000000..78ded5be54aac --- /dev/null +++ b/tests/baselines/reference/structuralTagTypes1.types @@ -0,0 +1,120 @@ +=== tests/cases/conformance/types/structuralTags/structuralTagTypes1.ts === +export type Paired = { +>Paired : Paired + + x: number & tag {x}; +>x : number & tag { x: any; } +>x : any + + y: number & tag {y}; +>y : number & tag { y: any; } +>y : any + +}; + + +export function isPaired(x: {x: number, y: number}): x is Paired { +>isPaired : (x: { x: number; y: number; }) => x is Paired +>x : { x: number; y: number; } +>x : number +>y : number + + return true; +>true : true +} + +export function makePair(x: number, y: number): Paired { +>makePair : (x: number, y: number) => Paired +>x : number +>y : number + + return {x, y} as Paired; +>{x, y} as Paired : Paired +>{x, y} : { x: number; y: number; } +>x : number +>y : number +} + +const a = makePair(0, 0); +>a : Paired +>makePair(0, 0) : Paired +>makePair : (x: number, y: number) => Paired +>0 : 0 +>0 : 0 + +const b = {x: 0, y: 0}; +>b : { x: number; y: number; } +>{x: 0, y: 0} : { x: number; y: number; } +>x : number +>0 : 0 +>y : number +>0 : 0 + +if (Math.random() > 0.3) { +>Math.random() > 0.3 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.3 : 0.3 + + b.x = a.x; +>b.x = a.x : number & tag { x: any; } +>b.x : number +>b : { x: number; y: number; } +>x : number +>a.x : number & tag { x: any; } +>a : Paired +>x : number & tag { x: any; } + + b.y = a.y; +>b.y = a.y : number & tag { y: any; } +>b.y : number +>b : { x: number; y: number; } +>y : number +>a.y : number & tag { y: any; } +>a : Paired +>y : number & tag { y: any; } +} + +if (isPaired(b)) { +>isPaired(b) : boolean +>isPaired : (x: { x: number; y: number; }) => x is Paired +>b : { x: number; y: number; } + + b.x = a.x; +>b.x = a.x : number & tag { x: any; } +>b.x : number & tag { x: any; } +>b : Paired +>x : number & tag { x: any; } +>a.x : number & tag { x: any; } +>a : Paired +>x : number & tag { x: any; } + + b.y = a.y; +>b.y = a.y : number & tag { y: any; } +>b.y : number & tag { y: any; } +>b : Paired +>y : number & tag { y: any; } +>a.y : number & tag { y: any; } +>a : Paired +>y : number & tag { y: any; } + + a.x = b.x; +>a.x = b.x : number & tag { x: any; } +>a.x : number & tag { x: any; } +>a : Paired +>x : number & tag { x: any; } +>b.x : number & tag { x: any; } +>b : Paired +>x : number & tag { x: any; } + + a.y = b.y; +>a.y = b.y : number & tag { y: any; } +>a.y : number & tag { y: any; } +>a : Paired +>y : number & tag { y: any; } +>b.y : number & tag { y: any; } +>b : Paired +>y : number & tag { y: any; } +} diff --git a/tests/baselines/reference/structuralTagTypesControlFlow.errors.txt b/tests/baselines/reference/structuralTagTypesControlFlow.errors.txt new file mode 100644 index 0000000000000..acfdcceae9190 --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesControlFlow.errors.txt @@ -0,0 +1,174 @@ +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(22,23): error TS2345: Argument of type '{ x: number; } & BrandA' is not assignable to parameter of type 'BrandB'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(24,27): error TS2345: Argument of type '{ x: number; } & BrandA' is not assignable to parameter of type 'tag ({ BrandA: void; } & { BrandB: void; })'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(29,23): error TS2345: Argument of type '{ x: number; } & BrandB' is not assignable to parameter of type 'BrandA'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(32,27): error TS2345: Argument of type '{ x: number; } & BrandB' is not assignable to parameter of type 'tag ({ BrandA: void; } & { BrandB: void; })'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(35,23): error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type 'BrandA'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(36,23): error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type 'BrandB'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(37,26): error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type 'BrandA | BrandB'. + Type '{ x: number; }' is not assignable to type 'BrandB'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(38,27): error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type 'tag ({ BrandA: void; } & { BrandB: void; })'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(64,29): error TS2345: Argument of type '"/a/b/c" & tag { NormalizedPath: void; }' is not assignable to parameter of type 'AbsolutePath'. + Type '"/a/b/c"' is not assignable to type 'AbsolutePath'. + Type '"/a/b/c"' is not assignable to type 'tag { AbsolutePath: void; }'. + Type '"/a/b/c" & tag { NormalizedPath: void; }' is not assignable to type 'tag { AbsolutePath: void; }'. + Type '"/a/b/c"' is not assignable to type 'tag { AbsolutePath: void; }'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(66,39): error TS2345: Argument of type '"/a/b/c" & tag { NormalizedPath: void; }' is not assignable to parameter of type 'NormalizedAbsolutePath'. + Type '"/a/b/c"' is not assignable to type 'NormalizedAbsolutePath'. + Type '"/a/b/c"' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. + Type '"/a/b/c" & tag { NormalizedPath: void; }' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. + Type '"/a/b/c"' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(71,31): error TS2345: Argument of type '"/a/b/c" & tag { AbsolutePath: void; }' is not assignable to parameter of type 'NormalizedPath'. + Type '"/a/b/c"' is not assignable to type 'NormalizedPath'. + Type '"/a/b/c"' is not assignable to type 'tag { NormalizedPath: void; }'. + Type '"/a/b/c" & tag { AbsolutePath: void; }' is not assignable to type 'tag { NormalizedPath: void; }'. + Type '"/a/b/c"' is not assignable to type 'tag { NormalizedPath: void; }'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(74,39): error TS2345: Argument of type '"/a/b/c" & tag { AbsolutePath: void; }' is not assignable to parameter of type 'NormalizedAbsolutePath'. + Type '"/a/b/c"' is not assignable to type 'NormalizedAbsolutePath'. + Type '"/a/b/c"' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. + Type '"/a/b/c" & tag { AbsolutePath: void; }' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. + Type '"/a/b/c"' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(77,31): error TS2345: Argument of type '"/a/b/c"' is not assignable to parameter of type 'NormalizedPath'. + Type '"/a/b/c"' is not assignable to type 'tag { NormalizedPath: void; }'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(78,29): error TS2345: Argument of type '"/a/b/c"' is not assignable to parameter of type 'AbsolutePath'. + Type '"/a/b/c"' is not assignable to type 'tag { AbsolutePath: void; }'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(79,41): error TS2345: Argument of type '"/a/b/c"' is not assignable to parameter of type 'NormalizedPath | AbsolutePath'. +tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts(80,39): error TS2345: Argument of type '"/a/b/c"' is not assignable to parameter of type 'NormalizedAbsolutePath'. + Type '"/a/b/c"' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. + + +==== tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts (16 errors) ==== + type BrandA = tag {BrandA: void}; + type BrandB = tag {BrandB: void}; + + declare function isBrandA(x: any): x is BrandA; + declare function isBrandB(x: any): x is BrandB; + + declare function consumeBrandA(x: BrandA): void; + declare function consumeBrandB(x: BrandB): void; + declare function consumeBrandAOrB(x: BrandA | BrandB): void; + declare function consumeBrandAAndB(x: BrandA & BrandB): void; + + const x = {x: 12}; + if (isBrandA(x)) { + if (isBrandB(x)) { + consumeBrandA(x); + consumeBrandB(x); + consumeBrandAOrB(x); + consumeBrandAAndB(x); + } + else { + consumeBrandA(x); + consumeBrandB(x); // err + ~ +!!! error TS2345: Argument of type '{ x: number; } & BrandA' is not assignable to parameter of type 'BrandB'. + consumeBrandAOrB(x); + consumeBrandAAndB(x); // err + ~ +!!! error TS2345: Argument of type '{ x: number; } & BrandA' is not assignable to parameter of type 'tag ({ BrandA: void; } & { BrandB: void; })'. + } + } + else { + if (isBrandB(x)) { + consumeBrandA(x); // err + ~ +!!! error TS2345: Argument of type '{ x: number; } & BrandB' is not assignable to parameter of type 'BrandA'. + consumeBrandB(x); + consumeBrandAOrB(x); + consumeBrandAAndB(x); // err + ~ +!!! error TS2345: Argument of type '{ x: number; } & BrandB' is not assignable to parameter of type 'tag ({ BrandA: void; } & { BrandB: void; })'. + } + else { + consumeBrandA(x); // err + ~ +!!! error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type 'BrandA'. + consumeBrandB(x); // err + ~ +!!! error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type 'BrandB'. + consumeBrandAOrB(x); // err + ~ +!!! error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type 'BrandA | BrandB'. +!!! error TS2345: Type '{ x: number; }' is not assignable to type 'BrandB'. + consumeBrandAAndB(x); // err + ~ +!!! error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type 'tag ({ BrandA: void; } & { BrandB: void; })'. + } + } + + type NormalizedPath = string & tag {NormalizedPath: void}; + type AbsolutePath = string & tag {AbsolutePath: void}; + type NormalizedAbsolutePath = NormalizedPath & AbsolutePath; + + declare function isNormalizedPath(x: string): x is NormalizedPath; + declare function isAbsolutePath(x: string): x is AbsolutePath; + + declare function consumeNormalizedPath(x: NormalizedPath): void; + declare function consumeAbsolutePath(x: AbsolutePath): void; + declare function consumeNormalizedOrAbsolutePath(x: NormalizedPath | AbsolutePath): void; + declare function consumeNormalizedAbsolutePath(x: NormalizedAbsolutePath): void; + + const p = "/a/b/c"; + if (isNormalizedPath(p)) { + if (isAbsolutePath(p)) { + consumeNormalizedPath(p); + consumeAbsolutePath(p); + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); + } + else { + consumeNormalizedPath(p); + consumeAbsolutePath(p); // err + ~ +!!! error TS2345: Argument of type '"/a/b/c" & tag { NormalizedPath: void; }' is not assignable to parameter of type 'AbsolutePath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'AbsolutePath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag { AbsolutePath: void; }'. +!!! error TS2345: Type '"/a/b/c" & tag { NormalizedPath: void; }' is not assignable to type 'tag { AbsolutePath: void; }'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag { AbsolutePath: void; }'. + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); // err + ~ +!!! error TS2345: Argument of type '"/a/b/c" & tag { NormalizedPath: void; }' is not assignable to parameter of type 'NormalizedAbsolutePath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'NormalizedAbsolutePath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. +!!! error TS2345: Type '"/a/b/c" & tag { NormalizedPath: void; }' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. + } + } + else { + if (isAbsolutePath(p)) { + consumeNormalizedPath(p); // err + ~ +!!! error TS2345: Argument of type '"/a/b/c" & tag { AbsolutePath: void; }' is not assignable to parameter of type 'NormalizedPath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'NormalizedPath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag { NormalizedPath: void; }'. +!!! error TS2345: Type '"/a/b/c" & tag { AbsolutePath: void; }' is not assignable to type 'tag { NormalizedPath: void; }'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag { NormalizedPath: void; }'. + consumeAbsolutePath(p); + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); // err + ~ +!!! error TS2345: Argument of type '"/a/b/c" & tag { AbsolutePath: void; }' is not assignable to parameter of type 'NormalizedAbsolutePath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'NormalizedAbsolutePath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. +!!! error TS2345: Type '"/a/b/c" & tag { AbsolutePath: void; }' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. + } + else { + consumeNormalizedPath(p); // err + ~ +!!! error TS2345: Argument of type '"/a/b/c"' is not assignable to parameter of type 'NormalizedPath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag { NormalizedPath: void; }'. + consumeAbsolutePath(p); // err + ~ +!!! error TS2345: Argument of type '"/a/b/c"' is not assignable to parameter of type 'AbsolutePath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag { AbsolutePath: void; }'. + consumeNormalizedOrAbsolutePath(p); // err + ~ +!!! error TS2345: Argument of type '"/a/b/c"' is not assignable to parameter of type 'NormalizedPath | AbsolutePath'. + consumeNormalizedAbsolutePath(p); // err + ~ +!!! error TS2345: Argument of type '"/a/b/c"' is not assignable to parameter of type 'NormalizedAbsolutePath'. +!!! error TS2345: Type '"/a/b/c"' is not assignable to type 'tag ({ NormalizedPath: void; } & { AbsolutePath: void; })'. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/structuralTagTypesControlFlow.js b/tests/baselines/reference/structuralTagTypesControlFlow.js new file mode 100644 index 0000000000000..9e07fc4d860f2 --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesControlFlow.js @@ -0,0 +1,144 @@ +//// [structuralTagTypesControlFlow.ts] +type BrandA = tag {BrandA: void}; +type BrandB = tag {BrandB: void}; + +declare function isBrandA(x: any): x is BrandA; +declare function isBrandB(x: any): x is BrandB; + +declare function consumeBrandA(x: BrandA): void; +declare function consumeBrandB(x: BrandB): void; +declare function consumeBrandAOrB(x: BrandA | BrandB): void; +declare function consumeBrandAAndB(x: BrandA & BrandB): void; + +const x = {x: 12}; +if (isBrandA(x)) { + if (isBrandB(x)) { + consumeBrandA(x); + consumeBrandB(x); + consumeBrandAOrB(x); + consumeBrandAAndB(x); + } + else { + consumeBrandA(x); + consumeBrandB(x); // err + consumeBrandAOrB(x); + consumeBrandAAndB(x); // err + } +} +else { + if (isBrandB(x)) { + consumeBrandA(x); // err + consumeBrandB(x); + consumeBrandAOrB(x); + consumeBrandAAndB(x); // err + } + else { + consumeBrandA(x); // err + consumeBrandB(x); // err + consumeBrandAOrB(x); // err + consumeBrandAAndB(x); // err + } +} + +type NormalizedPath = string & tag {NormalizedPath: void}; +type AbsolutePath = string & tag {AbsolutePath: void}; +type NormalizedAbsolutePath = NormalizedPath & AbsolutePath; + +declare function isNormalizedPath(x: string): x is NormalizedPath; +declare function isAbsolutePath(x: string): x is AbsolutePath; + +declare function consumeNormalizedPath(x: NormalizedPath): void; +declare function consumeAbsolutePath(x: AbsolutePath): void; +declare function consumeNormalizedOrAbsolutePath(x: NormalizedPath | AbsolutePath): void; +declare function consumeNormalizedAbsolutePath(x: NormalizedAbsolutePath): void; + +const p = "/a/b/c"; +if (isNormalizedPath(p)) { + if (isAbsolutePath(p)) { + consumeNormalizedPath(p); + consumeAbsolutePath(p); + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); + } + else { + consumeNormalizedPath(p); + consumeAbsolutePath(p); // err + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); // err + } +} +else { + if (isAbsolutePath(p)) { + consumeNormalizedPath(p); // err + consumeAbsolutePath(p); + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); // err + } + else { + consumeNormalizedPath(p); // err + consumeAbsolutePath(p); // err + consumeNormalizedOrAbsolutePath(p); // err + consumeNormalizedAbsolutePath(p); // err + } +} + + +//// [structuralTagTypesControlFlow.js] +var x = { x: 12 }; +if (isBrandA(x)) { + if (isBrandB(x)) { + consumeBrandA(x); + consumeBrandB(x); + consumeBrandAOrB(x); + consumeBrandAAndB(x); + } + else { + consumeBrandA(x); + consumeBrandB(x); // err + consumeBrandAOrB(x); + consumeBrandAAndB(x); // err + } +} +else { + if (isBrandB(x)) { + consumeBrandA(x); // err + consumeBrandB(x); + consumeBrandAOrB(x); + consumeBrandAAndB(x); // err + } + else { + consumeBrandA(x); // err + consumeBrandB(x); // err + consumeBrandAOrB(x); // err + consumeBrandAAndB(x); // err + } +} +var p = "/a/b/c"; +if (isNormalizedPath(p)) { + if (isAbsolutePath(p)) { + consumeNormalizedPath(p); + consumeAbsolutePath(p); + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); + } + else { + consumeNormalizedPath(p); + consumeAbsolutePath(p); // err + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); // err + } +} +else { + if (isAbsolutePath(p)) { + consumeNormalizedPath(p); // err + consumeAbsolutePath(p); + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); // err + } + else { + consumeNormalizedPath(p); // err + consumeAbsolutePath(p); // err + consumeNormalizedOrAbsolutePath(p); // err + consumeNormalizedAbsolutePath(p); // err + } +} diff --git a/tests/baselines/reference/structuralTagTypesControlFlow.symbols b/tests/baselines/reference/structuralTagTypesControlFlow.symbols new file mode 100644 index 0000000000000..f4b2ea78107ae --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesControlFlow.symbols @@ -0,0 +1,260 @@ +=== tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts === +type BrandA = tag {BrandA: void}; +>BrandA : Symbol(BrandA, Decl(structuralTagTypesControlFlow.ts, 0, 0)) +>BrandA : Symbol(BrandA, Decl(structuralTagTypesControlFlow.ts, 0, 19)) + +type BrandB = tag {BrandB: void}; +>BrandB : Symbol(BrandB, Decl(structuralTagTypesControlFlow.ts, 0, 33)) +>BrandB : Symbol(BrandB, Decl(structuralTagTypesControlFlow.ts, 1, 19)) + +declare function isBrandA(x: any): x is BrandA; +>isBrandA : Symbol(isBrandA, Decl(structuralTagTypesControlFlow.ts, 1, 33)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 3, 26)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 3, 26)) +>BrandA : Symbol(BrandA, Decl(structuralTagTypesControlFlow.ts, 0, 0)) + +declare function isBrandB(x: any): x is BrandB; +>isBrandB : Symbol(isBrandB, Decl(structuralTagTypesControlFlow.ts, 3, 47)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 4, 26)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 4, 26)) +>BrandB : Symbol(BrandB, Decl(structuralTagTypesControlFlow.ts, 0, 33)) + +declare function consumeBrandA(x: BrandA): void; +>consumeBrandA : Symbol(consumeBrandA, Decl(structuralTagTypesControlFlow.ts, 4, 47)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 6, 31)) +>BrandA : Symbol(BrandA, Decl(structuralTagTypesControlFlow.ts, 0, 0)) + +declare function consumeBrandB(x: BrandB): void; +>consumeBrandB : Symbol(consumeBrandB, Decl(structuralTagTypesControlFlow.ts, 6, 48)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 7, 31)) +>BrandB : Symbol(BrandB, Decl(structuralTagTypesControlFlow.ts, 0, 33)) + +declare function consumeBrandAOrB(x: BrandA | BrandB): void; +>consumeBrandAOrB : Symbol(consumeBrandAOrB, Decl(structuralTagTypesControlFlow.ts, 7, 48)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 8, 34)) +>BrandA : Symbol(BrandA, Decl(structuralTagTypesControlFlow.ts, 0, 0)) +>BrandB : Symbol(BrandB, Decl(structuralTagTypesControlFlow.ts, 0, 33)) + +declare function consumeBrandAAndB(x: BrandA & BrandB): void; +>consumeBrandAAndB : Symbol(consumeBrandAAndB, Decl(structuralTagTypesControlFlow.ts, 8, 60)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 9, 35)) +>BrandA : Symbol(BrandA, Decl(structuralTagTypesControlFlow.ts, 0, 0)) +>BrandB : Symbol(BrandB, Decl(structuralTagTypesControlFlow.ts, 0, 33)) + +const x = {x: 12}; +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 11)) + +if (isBrandA(x)) { +>isBrandA : Symbol(isBrandA, Decl(structuralTagTypesControlFlow.ts, 1, 33)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + if (isBrandB(x)) { +>isBrandB : Symbol(isBrandB, Decl(structuralTagTypesControlFlow.ts, 3, 47)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandA(x); +>consumeBrandA : Symbol(consumeBrandA, Decl(structuralTagTypesControlFlow.ts, 4, 47)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandB(x); +>consumeBrandB : Symbol(consumeBrandB, Decl(structuralTagTypesControlFlow.ts, 6, 48)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandAOrB(x); +>consumeBrandAOrB : Symbol(consumeBrandAOrB, Decl(structuralTagTypesControlFlow.ts, 7, 48)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandAAndB(x); +>consumeBrandAAndB : Symbol(consumeBrandAAndB, Decl(structuralTagTypesControlFlow.ts, 8, 60)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + } + else { + consumeBrandA(x); +>consumeBrandA : Symbol(consumeBrandA, Decl(structuralTagTypesControlFlow.ts, 4, 47)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandB(x); // err +>consumeBrandB : Symbol(consumeBrandB, Decl(structuralTagTypesControlFlow.ts, 6, 48)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandAOrB(x); +>consumeBrandAOrB : Symbol(consumeBrandAOrB, Decl(structuralTagTypesControlFlow.ts, 7, 48)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandAAndB(x); // err +>consumeBrandAAndB : Symbol(consumeBrandAAndB, Decl(structuralTagTypesControlFlow.ts, 8, 60)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + } +} +else { + if (isBrandB(x)) { +>isBrandB : Symbol(isBrandB, Decl(structuralTagTypesControlFlow.ts, 3, 47)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandA(x); // err +>consumeBrandA : Symbol(consumeBrandA, Decl(structuralTagTypesControlFlow.ts, 4, 47)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandB(x); +>consumeBrandB : Symbol(consumeBrandB, Decl(structuralTagTypesControlFlow.ts, 6, 48)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandAOrB(x); +>consumeBrandAOrB : Symbol(consumeBrandAOrB, Decl(structuralTagTypesControlFlow.ts, 7, 48)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandAAndB(x); // err +>consumeBrandAAndB : Symbol(consumeBrandAAndB, Decl(structuralTagTypesControlFlow.ts, 8, 60)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + } + else { + consumeBrandA(x); // err +>consumeBrandA : Symbol(consumeBrandA, Decl(structuralTagTypesControlFlow.ts, 4, 47)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandB(x); // err +>consumeBrandB : Symbol(consumeBrandB, Decl(structuralTagTypesControlFlow.ts, 6, 48)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandAOrB(x); // err +>consumeBrandAOrB : Symbol(consumeBrandAOrB, Decl(structuralTagTypesControlFlow.ts, 7, 48)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + + consumeBrandAAndB(x); // err +>consumeBrandAAndB : Symbol(consumeBrandAAndB, Decl(structuralTagTypesControlFlow.ts, 8, 60)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 11, 5)) + } +} + +type NormalizedPath = string & tag {NormalizedPath: void}; +>NormalizedPath : Symbol(NormalizedPath, Decl(structuralTagTypesControlFlow.ts, 39, 1)) +>NormalizedPath : Symbol(NormalizedPath, Decl(structuralTagTypesControlFlow.ts, 41, 36)) + +type AbsolutePath = string & tag {AbsolutePath: void}; +>AbsolutePath : Symbol(AbsolutePath, Decl(structuralTagTypesControlFlow.ts, 41, 58)) +>AbsolutePath : Symbol(AbsolutePath, Decl(structuralTagTypesControlFlow.ts, 42, 34)) + +type NormalizedAbsolutePath = NormalizedPath & AbsolutePath; +>NormalizedAbsolutePath : Symbol(NormalizedAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 42, 54)) +>NormalizedPath : Symbol(NormalizedPath, Decl(structuralTagTypesControlFlow.ts, 39, 1)) +>AbsolutePath : Symbol(AbsolutePath, Decl(structuralTagTypesControlFlow.ts, 41, 58)) + +declare function isNormalizedPath(x: string): x is NormalizedPath; +>isNormalizedPath : Symbol(isNormalizedPath, Decl(structuralTagTypesControlFlow.ts, 43, 60)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 45, 34)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 45, 34)) +>NormalizedPath : Symbol(NormalizedPath, Decl(structuralTagTypesControlFlow.ts, 39, 1)) + +declare function isAbsolutePath(x: string): x is AbsolutePath; +>isAbsolutePath : Symbol(isAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 45, 66)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 46, 32)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 46, 32)) +>AbsolutePath : Symbol(AbsolutePath, Decl(structuralTagTypesControlFlow.ts, 41, 58)) + +declare function consumeNormalizedPath(x: NormalizedPath): void; +>consumeNormalizedPath : Symbol(consumeNormalizedPath, Decl(structuralTagTypesControlFlow.ts, 46, 62)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 48, 39)) +>NormalizedPath : Symbol(NormalizedPath, Decl(structuralTagTypesControlFlow.ts, 39, 1)) + +declare function consumeAbsolutePath(x: AbsolutePath): void; +>consumeAbsolutePath : Symbol(consumeAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 48, 64)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 49, 37)) +>AbsolutePath : Symbol(AbsolutePath, Decl(structuralTagTypesControlFlow.ts, 41, 58)) + +declare function consumeNormalizedOrAbsolutePath(x: NormalizedPath | AbsolutePath): void; +>consumeNormalizedOrAbsolutePath : Symbol(consumeNormalizedOrAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 49, 60)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 50, 49)) +>NormalizedPath : Symbol(NormalizedPath, Decl(structuralTagTypesControlFlow.ts, 39, 1)) +>AbsolutePath : Symbol(AbsolutePath, Decl(structuralTagTypesControlFlow.ts, 41, 58)) + +declare function consumeNormalizedAbsolutePath(x: NormalizedAbsolutePath): void; +>consumeNormalizedAbsolutePath : Symbol(consumeNormalizedAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 50, 89)) +>x : Symbol(x, Decl(structuralTagTypesControlFlow.ts, 51, 47)) +>NormalizedAbsolutePath : Symbol(NormalizedAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 42, 54)) + +const p = "/a/b/c"; +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + +if (isNormalizedPath(p)) { +>isNormalizedPath : Symbol(isNormalizedPath, Decl(structuralTagTypesControlFlow.ts, 43, 60)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + if (isAbsolutePath(p)) { +>isAbsolutePath : Symbol(isAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 45, 66)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeNormalizedPath(p); +>consumeNormalizedPath : Symbol(consumeNormalizedPath, Decl(structuralTagTypesControlFlow.ts, 46, 62)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeAbsolutePath(p); +>consumeAbsolutePath : Symbol(consumeAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 48, 64)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeNormalizedOrAbsolutePath(p); +>consumeNormalizedOrAbsolutePath : Symbol(consumeNormalizedOrAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 49, 60)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeNormalizedAbsolutePath(p); +>consumeNormalizedAbsolutePath : Symbol(consumeNormalizedAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 50, 89)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + } + else { + consumeNormalizedPath(p); +>consumeNormalizedPath : Symbol(consumeNormalizedPath, Decl(structuralTagTypesControlFlow.ts, 46, 62)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeAbsolutePath(p); // err +>consumeAbsolutePath : Symbol(consumeAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 48, 64)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeNormalizedOrAbsolutePath(p); +>consumeNormalizedOrAbsolutePath : Symbol(consumeNormalizedOrAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 49, 60)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeNormalizedAbsolutePath(p); // err +>consumeNormalizedAbsolutePath : Symbol(consumeNormalizedAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 50, 89)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + } +} +else { + if (isAbsolutePath(p)) { +>isAbsolutePath : Symbol(isAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 45, 66)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeNormalizedPath(p); // err +>consumeNormalizedPath : Symbol(consumeNormalizedPath, Decl(structuralTagTypesControlFlow.ts, 46, 62)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeAbsolutePath(p); +>consumeAbsolutePath : Symbol(consumeAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 48, 64)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeNormalizedOrAbsolutePath(p); +>consumeNormalizedOrAbsolutePath : Symbol(consumeNormalizedOrAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 49, 60)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeNormalizedAbsolutePath(p); // err +>consumeNormalizedAbsolutePath : Symbol(consumeNormalizedAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 50, 89)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + } + else { + consumeNormalizedPath(p); // err +>consumeNormalizedPath : Symbol(consumeNormalizedPath, Decl(structuralTagTypesControlFlow.ts, 46, 62)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeAbsolutePath(p); // err +>consumeAbsolutePath : Symbol(consumeAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 48, 64)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeNormalizedOrAbsolutePath(p); // err +>consumeNormalizedOrAbsolutePath : Symbol(consumeNormalizedOrAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 49, 60)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + + consumeNormalizedAbsolutePath(p); // err +>consumeNormalizedAbsolutePath : Symbol(consumeNormalizedAbsolutePath, Decl(structuralTagTypesControlFlow.ts, 50, 89)) +>p : Symbol(p, Decl(structuralTagTypesControlFlow.ts, 53, 5)) + } +} + diff --git a/tests/baselines/reference/structuralTagTypesControlFlow.types b/tests/baselines/reference/structuralTagTypesControlFlow.types new file mode 100644 index 0000000000000..543c385336f6b --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesControlFlow.types @@ -0,0 +1,280 @@ +=== tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts === +type BrandA = tag {BrandA: void}; +>BrandA : BrandA +>BrandA : void + +type BrandB = tag {BrandB: void}; +>BrandB : BrandB +>BrandB : void + +declare function isBrandA(x: any): x is BrandA; +>isBrandA : (x: any) => x is BrandA +>x : any + +declare function isBrandB(x: any): x is BrandB; +>isBrandB : (x: any) => x is BrandB +>x : any + +declare function consumeBrandA(x: BrandA): void; +>consumeBrandA : (x: BrandA) => void +>x : BrandA + +declare function consumeBrandB(x: BrandB): void; +>consumeBrandB : (x: BrandB) => void +>x : BrandB + +declare function consumeBrandAOrB(x: BrandA | BrandB): void; +>consumeBrandAOrB : (x: BrandA | BrandB) => void +>x : BrandA | BrandB + +declare function consumeBrandAAndB(x: BrandA & BrandB): void; +>consumeBrandAAndB : (x: tag ({ BrandA: void; } & { BrandB: void; })) => void +>x : tag ({ BrandA: void; } & { BrandB: void; }) + +const x = {x: 12}; +>x : { x: number; } +>{x: 12} : { x: number; } +>x : number +>12 : 12 + +if (isBrandA(x)) { +>isBrandA(x) : boolean +>isBrandA : (x: any) => x is BrandA +>x : { x: number; } + + if (isBrandB(x)) { +>isBrandB(x) : boolean +>isBrandB : (x: any) => x is BrandB +>x : { x: number; } & BrandA + + consumeBrandA(x); +>consumeBrandA(x) : void +>consumeBrandA : (x: BrandA) => void +>x : { x: number; } & tag ({ BrandA: void; } & { BrandB: void; }) + + consumeBrandB(x); +>consumeBrandB(x) : void +>consumeBrandB : (x: BrandB) => void +>x : { x: number; } & tag ({ BrandA: void; } & { BrandB: void; }) + + consumeBrandAOrB(x); +>consumeBrandAOrB(x) : void +>consumeBrandAOrB : (x: BrandA | BrandB) => void +>x : { x: number; } & tag ({ BrandA: void; } & { BrandB: void; }) + + consumeBrandAAndB(x); +>consumeBrandAAndB(x) : void +>consumeBrandAAndB : (x: tag ({ BrandA: void; } & { BrandB: void; })) => void +>x : { x: number; } & tag ({ BrandA: void; } & { BrandB: void; }) + } + else { + consumeBrandA(x); +>consumeBrandA(x) : void +>consumeBrandA : (x: BrandA) => void +>x : { x: number; } & BrandA + + consumeBrandB(x); // err +>consumeBrandB(x) : void +>consumeBrandB : (x: BrandB) => void +>x : { x: number; } & BrandA + + consumeBrandAOrB(x); +>consumeBrandAOrB(x) : void +>consumeBrandAOrB : (x: BrandA | BrandB) => void +>x : { x: number; } & BrandA + + consumeBrandAAndB(x); // err +>consumeBrandAAndB(x) : void +>consumeBrandAAndB : (x: tag ({ BrandA: void; } & { BrandB: void; })) => void +>x : { x: number; } & BrandA + } +} +else { + if (isBrandB(x)) { +>isBrandB(x) : boolean +>isBrandB : (x: any) => x is BrandB +>x : { x: number; } + + consumeBrandA(x); // err +>consumeBrandA(x) : void +>consumeBrandA : (x: BrandA) => void +>x : { x: number; } & BrandB + + consumeBrandB(x); +>consumeBrandB(x) : void +>consumeBrandB : (x: BrandB) => void +>x : { x: number; } & BrandB + + consumeBrandAOrB(x); +>consumeBrandAOrB(x) : void +>consumeBrandAOrB : (x: BrandA | BrandB) => void +>x : { x: number; } & BrandB + + consumeBrandAAndB(x); // err +>consumeBrandAAndB(x) : void +>consumeBrandAAndB : (x: tag ({ BrandA: void; } & { BrandB: void; })) => void +>x : { x: number; } & BrandB + } + else { + consumeBrandA(x); // err +>consumeBrandA(x) : void +>consumeBrandA : (x: BrandA) => void +>x : { x: number; } + + consumeBrandB(x); // err +>consumeBrandB(x) : void +>consumeBrandB : (x: BrandB) => void +>x : { x: number; } + + consumeBrandAOrB(x); // err +>consumeBrandAOrB(x) : void +>consumeBrandAOrB : (x: BrandA | BrandB) => void +>x : { x: number; } + + consumeBrandAAndB(x); // err +>consumeBrandAAndB(x) : void +>consumeBrandAAndB : (x: tag ({ BrandA: void; } & { BrandB: void; })) => void +>x : { x: number; } + } +} + +type NormalizedPath = string & tag {NormalizedPath: void}; +>NormalizedPath : NormalizedPath +>NormalizedPath : void + +type AbsolutePath = string & tag {AbsolutePath: void}; +>AbsolutePath : AbsolutePath +>AbsolutePath : void + +type NormalizedAbsolutePath = NormalizedPath & AbsolutePath; +>NormalizedAbsolutePath : NormalizedAbsolutePath + +declare function isNormalizedPath(x: string): x is NormalizedPath; +>isNormalizedPath : (x: string) => x is NormalizedPath +>x : string + +declare function isAbsolutePath(x: string): x is AbsolutePath; +>isAbsolutePath : (x: string) => x is AbsolutePath +>x : string + +declare function consumeNormalizedPath(x: NormalizedPath): void; +>consumeNormalizedPath : (x: NormalizedPath) => void +>x : NormalizedPath + +declare function consumeAbsolutePath(x: AbsolutePath): void; +>consumeAbsolutePath : (x: AbsolutePath) => void +>x : AbsolutePath + +declare function consumeNormalizedOrAbsolutePath(x: NormalizedPath | AbsolutePath): void; +>consumeNormalizedOrAbsolutePath : (x: NormalizedPath | AbsolutePath) => void +>x : NormalizedPath | AbsolutePath + +declare function consumeNormalizedAbsolutePath(x: NormalizedAbsolutePath): void; +>consumeNormalizedAbsolutePath : (x: NormalizedAbsolutePath) => void +>x : NormalizedAbsolutePath + +const p = "/a/b/c"; +>p : "/a/b/c" +>"/a/b/c" : "/a/b/c" + +if (isNormalizedPath(p)) { +>isNormalizedPath(p) : boolean +>isNormalizedPath : (x: string) => x is NormalizedPath +>p : "/a/b/c" + + if (isAbsolutePath(p)) { +>isAbsolutePath(p) : boolean +>isAbsolutePath : (x: string) => x is AbsolutePath +>p : "/a/b/c" & tag { NormalizedPath: void; } + + consumeNormalizedPath(p); +>consumeNormalizedPath(p) : void +>consumeNormalizedPath : (x: NormalizedPath) => void +>p : "/a/b/c" & tag ({ NormalizedPath: void; } & { AbsolutePath: void; }) + + consumeAbsolutePath(p); +>consumeAbsolutePath(p) : void +>consumeAbsolutePath : (x: AbsolutePath) => void +>p : "/a/b/c" & tag ({ NormalizedPath: void; } & { AbsolutePath: void; }) + + consumeNormalizedOrAbsolutePath(p); +>consumeNormalizedOrAbsolutePath(p) : void +>consumeNormalizedOrAbsolutePath : (x: NormalizedPath | AbsolutePath) => void +>p : "/a/b/c" & tag ({ NormalizedPath: void; } & { AbsolutePath: void; }) + + consumeNormalizedAbsolutePath(p); +>consumeNormalizedAbsolutePath(p) : void +>consumeNormalizedAbsolutePath : (x: NormalizedAbsolutePath) => void +>p : "/a/b/c" & tag ({ NormalizedPath: void; } & { AbsolutePath: void; }) + } + else { + consumeNormalizedPath(p); +>consumeNormalizedPath(p) : void +>consumeNormalizedPath : (x: NormalizedPath) => void +>p : "/a/b/c" & tag { NormalizedPath: void; } + + consumeAbsolutePath(p); // err +>consumeAbsolutePath(p) : void +>consumeAbsolutePath : (x: AbsolutePath) => void +>p : "/a/b/c" & tag { NormalizedPath: void; } + + consumeNormalizedOrAbsolutePath(p); +>consumeNormalizedOrAbsolutePath(p) : void +>consumeNormalizedOrAbsolutePath : (x: NormalizedPath | AbsolutePath) => void +>p : "/a/b/c" & tag { NormalizedPath: void; } + + consumeNormalizedAbsolutePath(p); // err +>consumeNormalizedAbsolutePath(p) : void +>consumeNormalizedAbsolutePath : (x: NormalizedAbsolutePath) => void +>p : "/a/b/c" & tag { NormalizedPath: void; } + } +} +else { + if (isAbsolutePath(p)) { +>isAbsolutePath(p) : boolean +>isAbsolutePath : (x: string) => x is AbsolutePath +>p : "/a/b/c" + + consumeNormalizedPath(p); // err +>consumeNormalizedPath(p) : void +>consumeNormalizedPath : (x: NormalizedPath) => void +>p : "/a/b/c" & tag { AbsolutePath: void; } + + consumeAbsolutePath(p); +>consumeAbsolutePath(p) : void +>consumeAbsolutePath : (x: AbsolutePath) => void +>p : "/a/b/c" & tag { AbsolutePath: void; } + + consumeNormalizedOrAbsolutePath(p); +>consumeNormalizedOrAbsolutePath(p) : void +>consumeNormalizedOrAbsolutePath : (x: NormalizedPath | AbsolutePath) => void +>p : "/a/b/c" & tag { AbsolutePath: void; } + + consumeNormalizedAbsolutePath(p); // err +>consumeNormalizedAbsolutePath(p) : void +>consumeNormalizedAbsolutePath : (x: NormalizedAbsolutePath) => void +>p : "/a/b/c" & tag { AbsolutePath: void; } + } + else { + consumeNormalizedPath(p); // err +>consumeNormalizedPath(p) : void +>consumeNormalizedPath : (x: NormalizedPath) => void +>p : "/a/b/c" + + consumeAbsolutePath(p); // err +>consumeAbsolutePath(p) : void +>consumeAbsolutePath : (x: AbsolutePath) => void +>p : "/a/b/c" + + consumeNormalizedOrAbsolutePath(p); // err +>consumeNormalizedOrAbsolutePath(p) : void +>consumeNormalizedOrAbsolutePath : (x: NormalizedPath | AbsolutePath) => void +>p : "/a/b/c" + + consumeNormalizedAbsolutePath(p); // err +>consumeNormalizedAbsolutePath(p) : void +>consumeNormalizedAbsolutePath : (x: NormalizedAbsolutePath) => void +>p : "/a/b/c" + } +} + diff --git a/tests/baselines/reference/structuralTagTypesDeclarations.js b/tests/baselines/reference/structuralTagTypesDeclarations.js new file mode 100644 index 0000000000000..a4eac62e3135f --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesDeclarations.js @@ -0,0 +1,29 @@ +//// [structuralTagTypesDeclarations.ts] +export type Downcased = string & tag {downcased: void}; + +export function downcaseLit(x: T): T & Downcased { + return x.toLocaleLowerCase() as T & Downcased; +} +const a = "ok"; +export const c = downcaseLit(a); // no visibility error, tag reproduced structurally + + +//// [structuralTagTypesDeclarations.js] +"use strict"; +exports.__esModule = true; +function downcaseLit(x) { + return x.toLocaleLowerCase(); +} +exports.downcaseLit = downcaseLit; +var a = "ok"; +exports.c = downcaseLit(a); // no visibility error, tag reproduced structurally + + +//// [structuralTagTypesDeclarations.d.ts] +export declare type Downcased = string & tag { + downcased: void; +}; +export declare function downcaseLit(x: T): T & Downcased; +export declare const c: "ok" & tag { + downcased: void; +}; diff --git a/tests/baselines/reference/structuralTagTypesDeclarations.symbols b/tests/baselines/reference/structuralTagTypesDeclarations.symbols new file mode 100644 index 0000000000000..f32407f24880b --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesDeclarations.symbols @@ -0,0 +1,28 @@ +=== tests/cases/conformance/types/structuralTags/structuralTagTypesDeclarations.ts === +export type Downcased = string & tag {downcased: void}; +>Downcased : Symbol(Downcased, Decl(structuralTagTypesDeclarations.ts, 0, 0)) +>downcased : Symbol(downcased, Decl(structuralTagTypesDeclarations.ts, 0, 38)) + +export function downcaseLit(x: T): T & Downcased { +>downcaseLit : Symbol(downcaseLit, Decl(structuralTagTypesDeclarations.ts, 0, 55)) +>T : Symbol(T, Decl(structuralTagTypesDeclarations.ts, 2, 28)) +>x : Symbol(x, Decl(structuralTagTypesDeclarations.ts, 2, 46)) +>T : Symbol(T, Decl(structuralTagTypesDeclarations.ts, 2, 28)) +>T : Symbol(T, Decl(structuralTagTypesDeclarations.ts, 2, 28)) +>Downcased : Symbol(Downcased, Decl(structuralTagTypesDeclarations.ts, 0, 0)) + + return x.toLocaleLowerCase() as T & Downcased; +>x.toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(structuralTagTypesDeclarations.ts, 2, 46)) +>toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(structuralTagTypesDeclarations.ts, 2, 28)) +>Downcased : Symbol(Downcased, Decl(structuralTagTypesDeclarations.ts, 0, 0)) +} +const a = "ok"; +>a : Symbol(a, Decl(structuralTagTypesDeclarations.ts, 5, 5)) + +export const c = downcaseLit(a); // no visibility error, tag reproduced structurally +>c : Symbol(c, Decl(structuralTagTypesDeclarations.ts, 6, 12)) +>downcaseLit : Symbol(downcaseLit, Decl(structuralTagTypesDeclarations.ts, 0, 55)) +>a : Symbol(a, Decl(structuralTagTypesDeclarations.ts, 5, 5)) + diff --git a/tests/baselines/reference/structuralTagTypesDeclarations.types b/tests/baselines/reference/structuralTagTypesDeclarations.types new file mode 100644 index 0000000000000..b7bc921d9a4d2 --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesDeclarations.types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/types/structuralTags/structuralTagTypesDeclarations.ts === +export type Downcased = string & tag {downcased: void}; +>Downcased : Downcased +>downcased : void + +export function downcaseLit(x: T): T & Downcased { +>downcaseLit : (x: T) => T & string & tag { downcased: void; } +>x : T + + return x.toLocaleLowerCase() as T & Downcased; +>x.toLocaleLowerCase() as T & Downcased : T & string & tag { downcased: void; } +>x.toLocaleLowerCase() : string +>x.toLocaleLowerCase : (locales?: string | string[]) => string +>x : T +>toLocaleLowerCase : (locales?: string | string[]) => string +} +const a = "ok"; +>a : "ok" +>"ok" : "ok" + +export const c = downcaseLit(a); // no visibility error, tag reproduced structurally +>c : "ok" & tag { downcased: void; } +>downcaseLit(a) : "ok" & tag { downcased: void; } +>downcaseLit : (x: T) => T & string & tag { downcased: void; } +>a : "ok" + diff --git a/tests/baselines/reference/structuralTagTypesErr1.errors.txt b/tests/baselines/reference/structuralTagTypesErr1.errors.txt new file mode 100644 index 0000000000000..4ca5fc6aa8bf0 --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesErr1.errors.txt @@ -0,0 +1,70 @@ +tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts(18,1): error TS2322: Type 'number & tag { y: any; }' is not assignable to type 'number & tag { x: any; }'. + Type 'number' is not assignable to type 'number & tag { x: any; }'. + Type 'number' is not assignable to type 'tag { x: any; }'. + Type 'number & tag { y: any; }' is not assignable to type 'tag { x: any; }'. + Type 'number' is not assignable to type 'tag { x: any; }'. +tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts(19,1): error TS2322: Type 'number & tag { x: any; }' is not assignable to type 'number & tag { y: any; }'. + Type 'number' is not assignable to type 'number & tag { y: any; }'. + Type 'number' is not assignable to type 'tag { y: any; }'. + Type 'number & tag { x: any; }' is not assignable to type 'tag { y: any; }'. + Type 'number' is not assignable to type 'tag { y: any; }'. +tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts(21,1): error TS2322: Type 'number' is not assignable to type 'number & tag { x: any; }'. + Type 'number' is not assignable to type 'tag { x: any; }'. +tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts(22,1): error TS2322: Type 'number' is not assignable to type 'number & tag { y: any; }'. + Type 'number' is not assignable to type 'tag { y: any; }'. +tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts(24,1): error TS2322: Type 'number' is not assignable to type 'number & tag { x: any; }'. + Type 'number' is not assignable to type 'tag { x: any; }'. +tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts(25,1): error TS2322: Type 'number' is not assignable to type 'number & tag { y: any; }'. + Type 'number' is not assignable to type 'tag { y: any; }'. + + +==== tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts (6 errors) ==== + export type Paired = { + x: number & tag {x}; + y: number & tag {y}; + }; + + + export function isPaired(x: {x: number, y: number}): x is Paired { + return true; + } + + export function makePair(x: number, y: number): Paired { + return {x, y} as Paired; + } + + const a = makePair(0, 0); + const b = {x: 0, y: 0}; + + a.x = a.y; // err + ~~~ +!!! error TS2322: Type 'number & tag { y: any; }' is not assignable to type 'number & tag { x: any; }'. +!!! error TS2322: Type 'number' is not assignable to type 'number & tag { x: any; }'. +!!! error TS2322: Type 'number' is not assignable to type 'tag { x: any; }'. +!!! error TS2322: Type 'number & tag { y: any; }' is not assignable to type 'tag { x: any; }'. +!!! error TS2322: Type 'number' is not assignable to type 'tag { x: any; }'. + a.y = a.x; // err + ~~~ +!!! error TS2322: Type 'number & tag { x: any; }' is not assignable to type 'number & tag { y: any; }'. +!!! error TS2322: Type 'number' is not assignable to type 'number & tag { y: any; }'. +!!! error TS2322: Type 'number' is not assignable to type 'tag { y: any; }'. +!!! error TS2322: Type 'number & tag { x: any; }' is not assignable to type 'tag { y: any; }'. +!!! error TS2322: Type 'number' is not assignable to type 'tag { y: any; }'. + + a.x = b.y; // err + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'number & tag { x: any; }'. +!!! error TS2322: Type 'number' is not assignable to type 'tag { x: any; }'. + a.y = b.y; // err + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'number & tag { y: any; }'. +!!! error TS2322: Type 'number' is not assignable to type 'tag { y: any; }'. + + a.x = b.x; // err + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'number & tag { x: any; }'. +!!! error TS2322: Type 'number' is not assignable to type 'tag { x: any; }'. + a.y = b.x; // err + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'number & tag { y: any; }'. +!!! error TS2322: Type 'number' is not assignable to type 'tag { y: any; }'. \ No newline at end of file diff --git a/tests/baselines/reference/structuralTagTypesErr1.js b/tests/baselines/reference/structuralTagTypesErr1.js new file mode 100644 index 0000000000000..85ac3109ff855 --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesErr1.js @@ -0,0 +1,46 @@ +//// [structuralTagTypesErr1.ts] +export type Paired = { + x: number & tag {x}; + y: number & tag {y}; +}; + + +export function isPaired(x: {x: number, y: number}): x is Paired { + return true; +} + +export function makePair(x: number, y: number): Paired { + return {x, y} as Paired; +} + +const a = makePair(0, 0); +const b = {x: 0, y: 0}; + +a.x = a.y; // err +a.y = a.x; // err + +a.x = b.y; // err +a.y = b.y; // err + +a.x = b.x; // err +a.y = b.x; // err + +//// [structuralTagTypesErr1.js] +"use strict"; +exports.__esModule = true; +function isPaired(x) { + return true; +} +exports.isPaired = isPaired; +function makePair(x, y) { + return { x: x, y: y }; +} +exports.makePair = makePair; +var a = makePair(0, 0); +var b = { x: 0, y: 0 }; +a.x = a.y; // err +a.y = a.x; // err +a.x = b.y; // err +a.y = b.y; // err +a.x = b.x; // err +a.y = b.x; // err diff --git a/tests/baselines/reference/structuralTagTypesErr1.symbols b/tests/baselines/reference/structuralTagTypesErr1.symbols new file mode 100644 index 0000000000000..272e65a0d469e --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesErr1.symbols @@ -0,0 +1,95 @@ +=== tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts === +export type Paired = { +>Paired : Symbol(Paired, Decl(structuralTagTypesErr1.ts, 0, 0)) + + x: number & tag {x}; +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 0, 22)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 1, 21)) + + y: number & tag {y}; +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 1, 24)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 2, 21)) + +}; + + +export function isPaired(x: {x: number, y: number}): x is Paired { +>isPaired : Symbol(isPaired, Decl(structuralTagTypesErr1.ts, 3, 2)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 6, 25)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 6, 29)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 6, 39)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 6, 25)) +>Paired : Symbol(Paired, Decl(structuralTagTypesErr1.ts, 0, 0)) + + return true; +} + +export function makePair(x: number, y: number): Paired { +>makePair : Symbol(makePair, Decl(structuralTagTypesErr1.ts, 8, 1)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 10, 25)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 10, 35)) +>Paired : Symbol(Paired, Decl(structuralTagTypesErr1.ts, 0, 0)) + + return {x, y} as Paired; +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 11, 12)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 11, 14)) +>Paired : Symbol(Paired, Decl(structuralTagTypesErr1.ts, 0, 0)) +} + +const a = makePair(0, 0); +>a : Symbol(a, Decl(structuralTagTypesErr1.ts, 14, 5)) +>makePair : Symbol(makePair, Decl(structuralTagTypesErr1.ts, 8, 1)) + +const b = {x: 0, y: 0}; +>b : Symbol(b, Decl(structuralTagTypesErr1.ts, 15, 5)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 15, 11)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 15, 16)) + +a.x = a.y; // err +>a.x : Symbol(x, Decl(structuralTagTypesErr1.ts, 0, 22)) +>a : Symbol(a, Decl(structuralTagTypesErr1.ts, 14, 5)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 0, 22)) +>a.y : Symbol(y, Decl(structuralTagTypesErr1.ts, 1, 24)) +>a : Symbol(a, Decl(structuralTagTypesErr1.ts, 14, 5)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 1, 24)) + +a.y = a.x; // err +>a.y : Symbol(y, Decl(structuralTagTypesErr1.ts, 1, 24)) +>a : Symbol(a, Decl(structuralTagTypesErr1.ts, 14, 5)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 1, 24)) +>a.x : Symbol(x, Decl(structuralTagTypesErr1.ts, 0, 22)) +>a : Symbol(a, Decl(structuralTagTypesErr1.ts, 14, 5)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 0, 22)) + +a.x = b.y; // err +>a.x : Symbol(x, Decl(structuralTagTypesErr1.ts, 0, 22)) +>a : Symbol(a, Decl(structuralTagTypesErr1.ts, 14, 5)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 0, 22)) +>b.y : Symbol(y, Decl(structuralTagTypesErr1.ts, 15, 16)) +>b : Symbol(b, Decl(structuralTagTypesErr1.ts, 15, 5)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 15, 16)) + +a.y = b.y; // err +>a.y : Symbol(y, Decl(structuralTagTypesErr1.ts, 1, 24)) +>a : Symbol(a, Decl(structuralTagTypesErr1.ts, 14, 5)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 1, 24)) +>b.y : Symbol(y, Decl(structuralTagTypesErr1.ts, 15, 16)) +>b : Symbol(b, Decl(structuralTagTypesErr1.ts, 15, 5)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 15, 16)) + +a.x = b.x; // err +>a.x : Symbol(x, Decl(structuralTagTypesErr1.ts, 0, 22)) +>a : Symbol(a, Decl(structuralTagTypesErr1.ts, 14, 5)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 0, 22)) +>b.x : Symbol(x, Decl(structuralTagTypesErr1.ts, 15, 11)) +>b : Symbol(b, Decl(structuralTagTypesErr1.ts, 15, 5)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 15, 11)) + +a.y = b.x; // err +>a.y : Symbol(y, Decl(structuralTagTypesErr1.ts, 1, 24)) +>a : Symbol(a, Decl(structuralTagTypesErr1.ts, 14, 5)) +>y : Symbol(y, Decl(structuralTagTypesErr1.ts, 1, 24)) +>b.x : Symbol(x, Decl(structuralTagTypesErr1.ts, 15, 11)) +>b : Symbol(b, Decl(structuralTagTypesErr1.ts, 15, 5)) +>x : Symbol(x, Decl(structuralTagTypesErr1.ts, 15, 11)) + diff --git a/tests/baselines/reference/structuralTagTypesErr1.types b/tests/baselines/reference/structuralTagTypesErr1.types new file mode 100644 index 0000000000000..92820b492ff85 --- /dev/null +++ b/tests/baselines/reference/structuralTagTypesErr1.types @@ -0,0 +1,106 @@ +=== tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts === +export type Paired = { +>Paired : Paired + + x: number & tag {x}; +>x : number & tag { x: any; } +>x : any + + y: number & tag {y}; +>y : number & tag { y: any; } +>y : any + +}; + + +export function isPaired(x: {x: number, y: number}): x is Paired { +>isPaired : (x: { x: number; y: number; }) => x is Paired +>x : { x: number; y: number; } +>x : number +>y : number + + return true; +>true : true +} + +export function makePair(x: number, y: number): Paired { +>makePair : (x: number, y: number) => Paired +>x : number +>y : number + + return {x, y} as Paired; +>{x, y} as Paired : Paired +>{x, y} : { x: number; y: number; } +>x : number +>y : number +} + +const a = makePair(0, 0); +>a : Paired +>makePair(0, 0) : Paired +>makePair : (x: number, y: number) => Paired +>0 : 0 +>0 : 0 + +const b = {x: 0, y: 0}; +>b : { x: number; y: number; } +>{x: 0, y: 0} : { x: number; y: number; } +>x : number +>0 : 0 +>y : number +>0 : 0 + +a.x = a.y; // err +>a.x = a.y : number & tag { y: any; } +>a.x : number & tag { x: any; } +>a : Paired +>x : number & tag { x: any; } +>a.y : number & tag { y: any; } +>a : Paired +>y : number & tag { y: any; } + +a.y = a.x; // err +>a.y = a.x : number & tag { x: any; } +>a.y : number & tag { y: any; } +>a : Paired +>y : number & tag { y: any; } +>a.x : number & tag { x: any; } +>a : Paired +>x : number & tag { x: any; } + +a.x = b.y; // err +>a.x = b.y : number +>a.x : number & tag { x: any; } +>a : Paired +>x : number & tag { x: any; } +>b.y : number +>b : { x: number; y: number; } +>y : number + +a.y = b.y; // err +>a.y = b.y : number +>a.y : number & tag { y: any; } +>a : Paired +>y : number & tag { y: any; } +>b.y : number +>b : { x: number; y: number; } +>y : number + +a.x = b.x; // err +>a.x = b.x : number +>a.x : number & tag { x: any; } +>a : Paired +>x : number & tag { x: any; } +>b.x : number +>b : { x: number; y: number; } +>x : number + +a.y = b.x; // err +>a.y = b.x : number +>a.y : number & tag { y: any; } +>a : Paired +>y : number & tag { y: any; } +>b.x : number +>b : { x: number; y: number; } +>x : number + diff --git a/tests/cases/conformance/types/structuralTags/structuralTagTypes.ts b/tests/cases/conformance/types/structuralTags/structuralTagTypes.ts new file mode 100644 index 0000000000000..8d3ab4e0a862c --- /dev/null +++ b/tests/cases/conformance/types/structuralTags/structuralTagTypes.ts @@ -0,0 +1,55 @@ +// @declaration: true +export type Downcased = string & tag { downcased: void; }; +export type Analyzed = T & tag { analyzed: void; }; +export type Paired = { + x: number & tag {x: number;}; + y: number & tag {y: number;}; +}; + +export function downcase(x: string): Downcased { + return x.toLocaleLowerCase() as Downcased; +} + +export function downcaseLit(x: T): T & Downcased { + return x.toLocaleLowerCase() as T & Downcased; +} + +export function isDowncase(x: string): x is Downcased { + return null as any; +} + +export function analyze(x: T): Analyzed { + return x as Analyzed; +} + +export function isAnalyzed(x: T): x is Analyzed { + return Math.random() > 0.33 ? false : true; +} + +export function isPaired(x: {x: number, y: number}): x is Paired { + return true; +} + +export function makePair(x: number, y: number): Paired { + return {x, y} as Paired; +} + +const a = "ok"; +export const b = downcase(a); +export const d = downcaseLit(b); + +if (isDowncase(d)) { + d; +} + +const e = {data: { value: "str" }}; +export const f = analyze(e); +if (isAnalyzed(e)) { + e; +} + +export const g = makePair(0, 0); +const h = {x: 0, y: 0}; +if (isPaired(h)) { + h; +} diff --git a/tests/cases/conformance/types/structuralTags/structuralTagTypes1.ts b/tests/cases/conformance/types/structuralTags/structuralTagTypes1.ts new file mode 100644 index 0000000000000..8e917eab04fd1 --- /dev/null +++ b/tests/cases/conformance/types/structuralTags/structuralTagTypes1.ts @@ -0,0 +1,28 @@ +export type Paired = { + x: number & tag {x}; + y: number & tag {y}; +}; + + +export function isPaired(x: {x: number, y: number}): x is Paired { + return true; +} + +export function makePair(x: number, y: number): Paired { + return {x, y} as Paired; +} + +const a = makePair(0, 0); +const b = {x: 0, y: 0}; + +if (Math.random() > 0.3) { + b.x = a.x; + b.y = a.y; +} + +if (isPaired(b)) { + b.x = a.x; + b.y = a.y; + a.x = b.x; + a.y = b.y; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts b/tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts new file mode 100644 index 0000000000000..383c1f4a5adc5 --- /dev/null +++ b/tests/cases/conformance/types/structuralTags/structuralTagTypesControlFlow.ts @@ -0,0 +1,82 @@ +type BrandA = tag {BrandA: void}; +type BrandB = tag {BrandB: void}; + +declare function isBrandA(x: any): x is BrandA; +declare function isBrandB(x: any): x is BrandB; + +declare function consumeBrandA(x: BrandA): void; +declare function consumeBrandB(x: BrandB): void; +declare function consumeBrandAOrB(x: BrandA | BrandB): void; +declare function consumeBrandAAndB(x: BrandA & BrandB): void; + +const x = {x: 12}; +if (isBrandA(x)) { + if (isBrandB(x)) { + consumeBrandA(x); + consumeBrandB(x); + consumeBrandAOrB(x); + consumeBrandAAndB(x); + } + else { + consumeBrandA(x); + consumeBrandB(x); // err + consumeBrandAOrB(x); + consumeBrandAAndB(x); // err + } +} +else { + if (isBrandB(x)) { + consumeBrandA(x); // err + consumeBrandB(x); + consumeBrandAOrB(x); + consumeBrandAAndB(x); // err + } + else { + consumeBrandA(x); // err + consumeBrandB(x); // err + consumeBrandAOrB(x); // err + consumeBrandAAndB(x); // err + } +} + +type NormalizedPath = string & tag {NormalizedPath: void}; +type AbsolutePath = string & tag {AbsolutePath: void}; +type NormalizedAbsolutePath = NormalizedPath & AbsolutePath; + +declare function isNormalizedPath(x: string): x is NormalizedPath; +declare function isAbsolutePath(x: string): x is AbsolutePath; + +declare function consumeNormalizedPath(x: NormalizedPath): void; +declare function consumeAbsolutePath(x: AbsolutePath): void; +declare function consumeNormalizedOrAbsolutePath(x: NormalizedPath | AbsolutePath): void; +declare function consumeNormalizedAbsolutePath(x: NormalizedAbsolutePath): void; + +const p = "/a/b/c"; +if (isNormalizedPath(p)) { + if (isAbsolutePath(p)) { + consumeNormalizedPath(p); + consumeAbsolutePath(p); + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); + } + else { + consumeNormalizedPath(p); + consumeAbsolutePath(p); // err + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); // err + } +} +else { + if (isAbsolutePath(p)) { + consumeNormalizedPath(p); // err + consumeAbsolutePath(p); + consumeNormalizedOrAbsolutePath(p); + consumeNormalizedAbsolutePath(p); // err + } + else { + consumeNormalizedPath(p); // err + consumeAbsolutePath(p); // err + consumeNormalizedOrAbsolutePath(p); // err + consumeNormalizedAbsolutePath(p); // err + } +} diff --git a/tests/cases/conformance/types/structuralTags/structuralTagTypesDeclarations.ts b/tests/cases/conformance/types/structuralTags/structuralTagTypesDeclarations.ts new file mode 100644 index 0000000000000..f7d9f281090fa --- /dev/null +++ b/tests/cases/conformance/types/structuralTags/structuralTagTypesDeclarations.ts @@ -0,0 +1,8 @@ +// @declaration: true +export type Downcased = string & tag {downcased: void}; + +export function downcaseLit(x: T): T & Downcased { + return x.toLocaleLowerCase() as T & Downcased; +} +const a = "ok"; +export const c = downcaseLit(a); // no visibility error, tag reproduced structurally diff --git a/tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts b/tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts new file mode 100644 index 0000000000000..c2a02bf3253ad --- /dev/null +++ b/tests/cases/conformance/types/structuralTags/structuralTagTypesErr1.ts @@ -0,0 +1,25 @@ +export type Paired = { + x: number & tag {x}; + y: number & tag {y}; +}; + + +export function isPaired(x: {x: number, y: number}): x is Paired { + return true; +} + +export function makePair(x: number, y: number): Paired { + return {x, y} as Paired; +} + +const a = makePair(0, 0); +const b = {x: 0, y: 0}; + +a.x = a.y; // err +a.y = a.x; // err + +a.x = b.y; // err +a.y = b.y; // err + +a.x = b.x; // err +a.y = b.x; // err \ No newline at end of file