diff --git a/Herebyfile.mjs b/Herebyfile.mjs index 4e45a1b6a7a88..55270d9b70b1f 100644 --- a/Herebyfile.mjs +++ b/Herebyfile.mjs @@ -309,7 +309,7 @@ export const generateExtension = task({ const enumDefs = [ { name: "SymbolFlags", goPrefix: "SymbolFlags", goFile: "tsc/internal/ast/symbolflags.go", outDir: "packages/typescript/src/enums" }, { name: "CheckFlags", goPrefix: "CheckFlags", goFile: "tsc/internal/ast/checkflags.go", outDir: "packages/typescript/src/enums" }, - { name: "TypeFlags", goPrefix: "TypeFlags", goFile: "tsc/internal/checker/types.go", outDir: "packages/typescript/src/enums" }, + { name: "TypeFlags", goPrefix: "TypeFlags", goFile: "tsc/internal/checker/types.go", outDir: "packages/typescript/src/enums", excludeMembers: ["Reserved1", "Reserved2", "Reserved3", "IncludesConstrainedTypeVariable", "IncludesError", "IncludesNegated"] }, { name: "ObjectFlags", goPrefix: "ObjectFlags", goFile: "tsc/internal/checker/types.go", outDir: "packages/typescript/src/enums" }, { name: "SignatureFlags", goPrefix: "SignatureFlags", goFile: "tsc/internal/checker/types.go", outDir: "packages/typescript/src/enums" }, { name: "SignatureKind", goPrefix: "SignatureKind", goFile: "tsc/internal/checker/types.go", outDir: "packages/typescript/src/enums" }, diff --git a/packages/typescript/src/api/node/encoder.generated.ts b/packages/typescript/src/api/node/encoder.generated.ts index df5572d9690aa..b68b758bff9b8 100644 --- a/packages/typescript/src/api/node/encoder.generated.ts +++ b/packages/typescript/src/api/node/encoder.generated.ts @@ -77,7 +77,7 @@ export function getNodeCommonData(node: Node): number { case SyntaxKind.ObjectLiteralExpression: return ((node as ObjectLiteralExpression).multiLine ? 1 : 0) << 24; case SyntaxKind.TypeOperator: - return ((node as TypeOperatorNode).operator === SyntaxKind.ReadonlyKeyword ? 1 : (node as TypeOperatorNode).operator === SyntaxKind.UniqueKeyword ? 2 : 0) << 24; + return ((node as TypeOperatorNode).operator === SyntaxKind.ReadonlyKeyword ? 1 : (node as TypeOperatorNode).operator === SyntaxKind.UniqueKeyword ? 2 : (node as TypeOperatorNode).operator === SyntaxKind.NotKeyword ? 3 : 0) << 24; case SyntaxKind.ImportAttributes: return ((node as ImportAttributes).multiLine ? 1 : 0) << 24 | ((node as ImportAttributes).token === SyntaxKind.AssertKeyword ? 1 : 0) << 25; case SyntaxKind.JsxText: diff --git a/packages/typescript/src/api/node/node.generated.ts b/packages/typescript/src/api/node/node.generated.ts index d9a8092261627..bfc1ec1e7241f 100644 --- a/packages/typescript/src/api/node/node.generated.ts +++ b/packages/typescript/src/api/node/node.generated.ts @@ -519,6 +519,7 @@ export class RemoteNode extends RemoteNodeBase implements Node { const idx = (this.data >> 24) & 0x3; if (idx === 1) return SyntaxKind.ReadonlyKeyword; if (idx === 2) return SyntaxKind.UniqueKeyword; + if (idx === 3) return SyntaxKind.NotKeyword; return SyntaxKind.KeyOfKeyword; } } diff --git a/packages/typescript/src/ast/ast.generated.ts b/packages/typescript/src/ast/ast.generated.ts index 76ddfe362ae96..4f00075bf8776 100644 --- a/packages/typescript/src/ast/ast.generated.ts +++ b/packages/typescript/src/ast/ast.generated.ts @@ -140,6 +140,7 @@ export type KeywordSyntaxKind = | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword + | SyntaxKind.NotKeyword | SyntaxKind.OutKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword @@ -311,6 +312,7 @@ export type TokenSyntaxKind = | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword + | SyntaxKind.NotKeyword | SyntaxKind.OutKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword @@ -962,7 +964,7 @@ export interface ConditionalTypeNode extends TypeNodeBase { } export interface TypeOperatorNode extends TypeNodeBase { readonly kind: SyntaxKind.TypeOperator; - readonly operator: SyntaxKind.KeyOfKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.UniqueKeyword; + readonly operator: SyntaxKind.KeyOfKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.NotKeyword; readonly type: TypeNode; } export interface InferTypeNode extends TypeNodeBase { diff --git a/packages/typescript/src/ast/factory.generated.ts b/packages/typescript/src/ast/factory.generated.ts index 787aa5910c820..87b97d44b7538 100644 --- a/packages/typescript/src/ast/factory.generated.ts +++ b/packages/typescript/src/ast/factory.generated.ts @@ -2451,7 +2451,7 @@ export function createConditionalTypeNode(checkType: TypeNode, extendsType: Type }) as unknown as ConditionalTypeNode; } -export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.UniqueKeyword, type: TypeNode): TypeOperatorNode { +export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.NotKeyword, type: TypeNode): TypeOperatorNode { return new NodeObject(SyntaxKind.TypeOperator, { operator, type, diff --git a/packages/typescript/src/enums/objectFlags.enum.ts b/packages/typescript/src/enums/objectFlags.enum.ts index 63ed4e4d3c93f..e4b4bc90ab436 100644 --- a/packages/typescript/src/enums/objectFlags.enum.ts +++ b/packages/typescript/src/enums/objectFlags.enum.ts @@ -50,4 +50,5 @@ export enum ObjectFlags { IsNeverIntersectionComputed = 1 << 25, IsNeverIntersection = 1 << 26, IsConstrainedTypeVariable = 1 << 27, + FreshNegated = 1 << 25, } diff --git a/packages/typescript/src/enums/objectFlags.ts b/packages/typescript/src/enums/objectFlags.ts index 1c17a70d5f797..5b364b40213a5 100644 --- a/packages/typescript/src/enums/objectFlags.ts +++ b/packages/typescript/src/enums/objectFlags.ts @@ -50,4 +50,5 @@ export var ObjectFlags: any; ObjectFlags[ObjectFlags["IsNeverIntersectionComputed"] = 33554432] = "IsNeverIntersectionComputed"; ObjectFlags[ObjectFlags["IsNeverIntersection"] = 67108864] = "IsNeverIntersection"; ObjectFlags[ObjectFlags["IsConstrainedTypeVariable"] = 134217728] = "IsConstrainedTypeVariable"; + ObjectFlags[ObjectFlags["FreshNegated"] = 33554432] = "FreshNegated"; })(ObjectFlags || (ObjectFlags = {})); diff --git a/packages/typescript/src/enums/syntaxKind.enum.ts b/packages/typescript/src/enums/syntaxKind.enum.ts index 400c16806abf5..7e1f4279882a2 100644 --- a/packages/typescript/src/enums/syntaxKind.enum.ts +++ b/packages/typescript/src/enums/syntaxKind.enum.ts @@ -148,211 +148,212 @@ export enum SyntaxKind { ModuleKeyword = 144, NamespaceKeyword = 145, NeverKeyword = 146, - OutKeyword = 147, - ReadonlyKeyword = 148, - RequireKeyword = 149, - NumberKeyword = 150, - ObjectKeyword = 151, - SatisfiesKeyword = 152, - SetKeyword = 153, - StringKeyword = 154, - SymbolKeyword = 155, - TypeKeyword = 156, - UndefinedKeyword = 157, - UniqueKeyword = 158, - UnknownKeyword = 159, - UsingKeyword = 160, - FromKeyword = 161, - GlobalKeyword = 162, - BigIntKeyword = 163, - OverrideKeyword = 164, - OfKeyword = 165, - DeferKeyword = 166, - QualifiedName = 167, - ComputedPropertyName = 168, - TypeParameter = 169, - Parameter = 170, - Decorator = 171, - PropertySignature = 172, - PropertyDeclaration = 173, - MethodSignature = 174, - MethodDeclaration = 175, - ClassStaticBlockDeclaration = 176, - Constructor = 177, - GetAccessor = 178, - SetAccessor = 179, - CallSignature = 180, - ConstructSignature = 181, - IndexSignature = 182, - TypePredicate = 183, - TypeReference = 184, - FunctionType = 185, - ConstructorType = 186, - TypeQuery = 187, - TypeLiteral = 188, - ArrayType = 189, - TupleType = 190, - OptionalType = 191, - RestType = 192, - UnionType = 193, - IntersectionType = 194, - ConditionalType = 195, - InferType = 196, - ParenthesizedType = 197, - ThisType = 198, - TypeOperator = 199, - IndexedAccessType = 200, - MappedType = 201, - LiteralType = 202, - NamedTupleMember = 203, - TemplateLiteralType = 204, - TemplateLiteralTypeSpan = 205, - ImportType = 206, - ObjectBindingPattern = 207, - ArrayBindingPattern = 208, - BindingElement = 209, - ArrayLiteralExpression = 210, - ObjectLiteralExpression = 211, - PropertyAccessExpression = 212, - ElementAccessExpression = 213, - CallExpression = 214, - NewExpression = 215, - TaggedTemplateExpression = 216, - TypeAssertionExpression = 217, - ParenthesizedExpression = 218, - FunctionExpression = 219, - ArrowFunction = 220, - DeleteExpression = 221, - TypeOfExpression = 222, - VoidExpression = 223, - AwaitExpression = 224, - PrefixUnaryExpression = 225, - PostfixUnaryExpression = 226, - BinaryExpression = 227, - ConditionalExpression = 228, - TemplateExpression = 229, - YieldExpression = 230, - SpreadElement = 231, - ClassExpression = 232, - OmittedExpression = 233, - ExpressionWithTypeArguments = 234, - AsExpression = 235, - NonNullExpression = 236, - MetaProperty = 237, - SyntheticExpression = 238, - SatisfiesExpression = 239, - TemplateSpan = 240, - SemicolonClassElement = 241, - Block = 242, - EmptyStatement = 243, - VariableStatement = 244, - ExpressionStatement = 245, - IfStatement = 246, - DoStatement = 247, - WhileStatement = 248, - ForStatement = 249, - ForInStatement = 250, - ForOfStatement = 251, - ContinueStatement = 252, - BreakStatement = 253, - ReturnStatement = 254, - WithStatement = 255, - SwitchStatement = 256, - LabeledStatement = 257, - ThrowStatement = 258, - TryStatement = 259, - DebuggerStatement = 260, - VariableDeclaration = 261, - VariableDeclarationList = 262, - FunctionDeclaration = 263, - ClassDeclaration = 264, - InterfaceDeclaration = 265, - TypeAliasDeclaration = 266, - EnumDeclaration = 267, - ModuleDeclaration = 268, - ModuleBlock = 269, - CaseBlock = 270, - NamespaceExportDeclaration = 271, - ImportEqualsDeclaration = 272, - ImportDeclaration = 273, - ImportClause = 274, - NamespaceImport = 275, - NamedImports = 276, - ImportSpecifier = 277, - ExportAssignment = 278, - ExportDeclaration = 279, - NamedExports = 280, - NamespaceExport = 281, - ExportSpecifier = 282, - MissingDeclaration = 283, - ExternalModuleReference = 284, - JsxElement = 285, - JsxSelfClosingElement = 286, - JsxOpeningElement = 287, - JsxClosingElement = 288, - JsxFragment = 289, - JsxOpeningFragment = 290, - JsxClosingFragment = 291, - JsxAttribute = 292, - JsxAttributes = 293, - JsxSpreadAttribute = 294, - JsxExpression = 295, - JsxNamespacedName = 296, - CaseClause = 297, - DefaultClause = 298, - HeritageClause = 299, - CatchClause = 300, - ImportAttributes = 301, - ImportAttribute = 302, - PropertyAssignment = 303, - ShorthandPropertyAssignment = 304, - SpreadAssignment = 305, - EnumMember = 306, - SourceFile = 307, - JSDocTypeExpression = 308, - JSDocNameReference = 309, - JSDocAllType = 310, - JSDocNullableType = 311, - JSDocNonNullableType = 312, - JSDocOptionalType = 313, - JSDocVariadicType = 314, - JSDoc = 315, - JSDocText = 316, - JSDocTypeLiteral = 317, - JSDocSignature = 318, - JSDocLink = 319, - JSDocLinkCode = 320, - JSDocLinkPlain = 321, - JSDocUnknownTag = 322, - JSDocAugmentsTag = 323, - JSDocImplementsTag = 324, - JSDocDeprecatedTag = 325, - JSDocPublicTag = 326, - JSDocPrivateTag = 327, - JSDocProtectedTag = 328, - JSDocReadonlyTag = 329, - JSDocOverrideTag = 330, - JSDocCallbackTag = 331, - JSDocOverloadTag = 332, - JSDocParameterTag = 333, - JSDocReturnTag = 334, - JSDocThisTag = 335, - JSDocTypeTag = 336, - JSDocTemplateTag = 337, - JSDocTypedefTag = 338, - JSDocSeeTag = 339, - JSDocPropertyTag = 340, - JSDocThrowsTag = 341, - JSDocSatisfiesTag = 342, - JSDocImportTag = 343, - SyntaxList = 344, - JSTypeAliasDeclaration = 345, - JSImportDeclaration = 346, - NotEmittedStatement = 347, - PartiallyEmittedExpression = 348, - SyntheticReferenceExpression = 349, - NotEmittedTypeElement = 350, - Count = 351, + NotKeyword = 147, + OutKeyword = 148, + ReadonlyKeyword = 149, + RequireKeyword = 150, + NumberKeyword = 151, + ObjectKeyword = 152, + SatisfiesKeyword = 153, + SetKeyword = 154, + StringKeyword = 155, + SymbolKeyword = 156, + TypeKeyword = 157, + UndefinedKeyword = 158, + UniqueKeyword = 159, + UnknownKeyword = 160, + UsingKeyword = 161, + FromKeyword = 162, + GlobalKeyword = 163, + BigIntKeyword = 164, + OverrideKeyword = 165, + OfKeyword = 166, + DeferKeyword = 167, + QualifiedName = 168, + ComputedPropertyName = 169, + TypeParameter = 170, + Parameter = 171, + Decorator = 172, + PropertySignature = 173, + PropertyDeclaration = 174, + MethodSignature = 175, + MethodDeclaration = 176, + ClassStaticBlockDeclaration = 177, + Constructor = 178, + GetAccessor = 179, + SetAccessor = 180, + CallSignature = 181, + ConstructSignature = 182, + IndexSignature = 183, + TypePredicate = 184, + TypeReference = 185, + FunctionType = 186, + ConstructorType = 187, + TypeQuery = 188, + TypeLiteral = 189, + ArrayType = 190, + TupleType = 191, + OptionalType = 192, + RestType = 193, + UnionType = 194, + IntersectionType = 195, + ConditionalType = 196, + InferType = 197, + ParenthesizedType = 198, + ThisType = 199, + TypeOperator = 200, + IndexedAccessType = 201, + MappedType = 202, + LiteralType = 203, + NamedTupleMember = 204, + TemplateLiteralType = 205, + TemplateLiteralTypeSpan = 206, + ImportType = 207, + ObjectBindingPattern = 208, + ArrayBindingPattern = 209, + BindingElement = 210, + ArrayLiteralExpression = 211, + ObjectLiteralExpression = 212, + PropertyAccessExpression = 213, + ElementAccessExpression = 214, + CallExpression = 215, + NewExpression = 216, + TaggedTemplateExpression = 217, + TypeAssertionExpression = 218, + ParenthesizedExpression = 219, + FunctionExpression = 220, + ArrowFunction = 221, + DeleteExpression = 222, + TypeOfExpression = 223, + VoidExpression = 224, + AwaitExpression = 225, + PrefixUnaryExpression = 226, + PostfixUnaryExpression = 227, + BinaryExpression = 228, + ConditionalExpression = 229, + TemplateExpression = 230, + YieldExpression = 231, + SpreadElement = 232, + ClassExpression = 233, + OmittedExpression = 234, + ExpressionWithTypeArguments = 235, + AsExpression = 236, + NonNullExpression = 237, + MetaProperty = 238, + SyntheticExpression = 239, + SatisfiesExpression = 240, + TemplateSpan = 241, + SemicolonClassElement = 242, + Block = 243, + EmptyStatement = 244, + VariableStatement = 245, + ExpressionStatement = 246, + IfStatement = 247, + DoStatement = 248, + WhileStatement = 249, + ForStatement = 250, + ForInStatement = 251, + ForOfStatement = 252, + ContinueStatement = 253, + BreakStatement = 254, + ReturnStatement = 255, + WithStatement = 256, + SwitchStatement = 257, + LabeledStatement = 258, + ThrowStatement = 259, + TryStatement = 260, + DebuggerStatement = 261, + VariableDeclaration = 262, + VariableDeclarationList = 263, + FunctionDeclaration = 264, + ClassDeclaration = 265, + InterfaceDeclaration = 266, + TypeAliasDeclaration = 267, + EnumDeclaration = 268, + ModuleDeclaration = 269, + ModuleBlock = 270, + CaseBlock = 271, + NamespaceExportDeclaration = 272, + ImportEqualsDeclaration = 273, + ImportDeclaration = 274, + ImportClause = 275, + NamespaceImport = 276, + NamedImports = 277, + ImportSpecifier = 278, + ExportAssignment = 279, + ExportDeclaration = 280, + NamedExports = 281, + NamespaceExport = 282, + ExportSpecifier = 283, + MissingDeclaration = 284, + ExternalModuleReference = 285, + JsxElement = 286, + JsxSelfClosingElement = 287, + JsxOpeningElement = 288, + JsxClosingElement = 289, + JsxFragment = 290, + JsxOpeningFragment = 291, + JsxClosingFragment = 292, + JsxAttribute = 293, + JsxAttributes = 294, + JsxSpreadAttribute = 295, + JsxExpression = 296, + JsxNamespacedName = 297, + CaseClause = 298, + DefaultClause = 299, + HeritageClause = 300, + CatchClause = 301, + ImportAttributes = 302, + ImportAttribute = 303, + PropertyAssignment = 304, + ShorthandPropertyAssignment = 305, + SpreadAssignment = 306, + EnumMember = 307, + SourceFile = 308, + JSDocTypeExpression = 309, + JSDocNameReference = 310, + JSDocAllType = 311, + JSDocNullableType = 312, + JSDocNonNullableType = 313, + JSDocOptionalType = 314, + JSDocVariadicType = 315, + JSDoc = 316, + JSDocText = 317, + JSDocTypeLiteral = 318, + JSDocSignature = 319, + JSDocLink = 320, + JSDocLinkCode = 321, + JSDocLinkPlain = 322, + JSDocUnknownTag = 323, + JSDocAugmentsTag = 324, + JSDocImplementsTag = 325, + JSDocDeprecatedTag = 326, + JSDocPublicTag = 327, + JSDocPrivateTag = 328, + JSDocProtectedTag = 329, + JSDocReadonlyTag = 330, + JSDocOverrideTag = 331, + JSDocCallbackTag = 332, + JSDocOverloadTag = 333, + JSDocParameterTag = 334, + JSDocReturnTag = 335, + JSDocThisTag = 336, + JSDocTypeTag = 337, + JSDocTemplateTag = 338, + JSDocTypedefTag = 339, + JSDocSeeTag = 340, + JSDocPropertyTag = 341, + JSDocThrowsTag = 342, + JSDocSatisfiesTag = 343, + JSDocImportTag = 344, + SyntaxList = 345, + JSTypeAliasDeclaration = 346, + JSImportDeclaration = 347, + NotEmittedStatement = 348, + PartiallyEmittedExpression = 349, + SyntheticReferenceExpression = 350, + NotEmittedTypeElement = 351, + Count = 352, FirstAssignment = EqualsToken, LastAssignment = CaretEqualsToken, FirstCompoundAssignment = PlusEqualsToken, diff --git a/packages/typescript/src/enums/syntaxKind.ts b/packages/typescript/src/enums/syntaxKind.ts index 87c2385c7cd47..827e56ced07f4 100644 --- a/packages/typescript/src/enums/syntaxKind.ts +++ b/packages/typescript/src/enums/syntaxKind.ts @@ -148,211 +148,212 @@ export var SyntaxKind: any; SyntaxKind[SyntaxKind["ModuleKeyword"] = 144] = "ModuleKeyword"; SyntaxKind[SyntaxKind["NamespaceKeyword"] = 145] = "NamespaceKeyword"; SyntaxKind[SyntaxKind["NeverKeyword"] = 146] = "NeverKeyword"; - SyntaxKind[SyntaxKind["OutKeyword"] = 147] = "OutKeyword"; - SyntaxKind[SyntaxKind["ReadonlyKeyword"] = 148] = "ReadonlyKeyword"; - SyntaxKind[SyntaxKind["RequireKeyword"] = 149] = "RequireKeyword"; - SyntaxKind[SyntaxKind["NumberKeyword"] = 150] = "NumberKeyword"; - SyntaxKind[SyntaxKind["ObjectKeyword"] = 151] = "ObjectKeyword"; - SyntaxKind[SyntaxKind["SatisfiesKeyword"] = 152] = "SatisfiesKeyword"; - SyntaxKind[SyntaxKind["SetKeyword"] = 153] = "SetKeyword"; - SyntaxKind[SyntaxKind["StringKeyword"] = 154] = "StringKeyword"; - SyntaxKind[SyntaxKind["SymbolKeyword"] = 155] = "SymbolKeyword"; - SyntaxKind[SyntaxKind["TypeKeyword"] = 156] = "TypeKeyword"; - SyntaxKind[SyntaxKind["UndefinedKeyword"] = 157] = "UndefinedKeyword"; - SyntaxKind[SyntaxKind["UniqueKeyword"] = 158] = "UniqueKeyword"; - SyntaxKind[SyntaxKind["UnknownKeyword"] = 159] = "UnknownKeyword"; - SyntaxKind[SyntaxKind["UsingKeyword"] = 160] = "UsingKeyword"; - SyntaxKind[SyntaxKind["FromKeyword"] = 161] = "FromKeyword"; - SyntaxKind[SyntaxKind["GlobalKeyword"] = 162] = "GlobalKeyword"; - SyntaxKind[SyntaxKind["BigIntKeyword"] = 163] = "BigIntKeyword"; - SyntaxKind[SyntaxKind["OverrideKeyword"] = 164] = "OverrideKeyword"; - SyntaxKind[SyntaxKind["OfKeyword"] = 165] = "OfKeyword"; - SyntaxKind[SyntaxKind["DeferKeyword"] = 166] = "DeferKeyword"; - SyntaxKind[SyntaxKind["QualifiedName"] = 167] = "QualifiedName"; - SyntaxKind[SyntaxKind["ComputedPropertyName"] = 168] = "ComputedPropertyName"; - SyntaxKind[SyntaxKind["TypeParameter"] = 169] = "TypeParameter"; - SyntaxKind[SyntaxKind["Parameter"] = 170] = "Parameter"; - SyntaxKind[SyntaxKind["Decorator"] = 171] = "Decorator"; - SyntaxKind[SyntaxKind["PropertySignature"] = 172] = "PropertySignature"; - SyntaxKind[SyntaxKind["PropertyDeclaration"] = 173] = "PropertyDeclaration"; - SyntaxKind[SyntaxKind["MethodSignature"] = 174] = "MethodSignature"; - SyntaxKind[SyntaxKind["MethodDeclaration"] = 175] = "MethodDeclaration"; - SyntaxKind[SyntaxKind["ClassStaticBlockDeclaration"] = 176] = "ClassStaticBlockDeclaration"; - SyntaxKind[SyntaxKind["Constructor"] = 177] = "Constructor"; - SyntaxKind[SyntaxKind["GetAccessor"] = 178] = "GetAccessor"; - SyntaxKind[SyntaxKind["SetAccessor"] = 179] = "SetAccessor"; - SyntaxKind[SyntaxKind["CallSignature"] = 180] = "CallSignature"; - SyntaxKind[SyntaxKind["ConstructSignature"] = 181] = "ConstructSignature"; - SyntaxKind[SyntaxKind["IndexSignature"] = 182] = "IndexSignature"; - SyntaxKind[SyntaxKind["TypePredicate"] = 183] = "TypePredicate"; - SyntaxKind[SyntaxKind["TypeReference"] = 184] = "TypeReference"; - SyntaxKind[SyntaxKind["FunctionType"] = 185] = "FunctionType"; - SyntaxKind[SyntaxKind["ConstructorType"] = 186] = "ConstructorType"; - SyntaxKind[SyntaxKind["TypeQuery"] = 187] = "TypeQuery"; - SyntaxKind[SyntaxKind["TypeLiteral"] = 188] = "TypeLiteral"; - SyntaxKind[SyntaxKind["ArrayType"] = 189] = "ArrayType"; - SyntaxKind[SyntaxKind["TupleType"] = 190] = "TupleType"; - SyntaxKind[SyntaxKind["OptionalType"] = 191] = "OptionalType"; - SyntaxKind[SyntaxKind["RestType"] = 192] = "RestType"; - SyntaxKind[SyntaxKind["UnionType"] = 193] = "UnionType"; - SyntaxKind[SyntaxKind["IntersectionType"] = 194] = "IntersectionType"; - SyntaxKind[SyntaxKind["ConditionalType"] = 195] = "ConditionalType"; - SyntaxKind[SyntaxKind["InferType"] = 196] = "InferType"; - SyntaxKind[SyntaxKind["ParenthesizedType"] = 197] = "ParenthesizedType"; - SyntaxKind[SyntaxKind["ThisType"] = 198] = "ThisType"; - SyntaxKind[SyntaxKind["TypeOperator"] = 199] = "TypeOperator"; - SyntaxKind[SyntaxKind["IndexedAccessType"] = 200] = "IndexedAccessType"; - SyntaxKind[SyntaxKind["MappedType"] = 201] = "MappedType"; - SyntaxKind[SyntaxKind["LiteralType"] = 202] = "LiteralType"; - SyntaxKind[SyntaxKind["NamedTupleMember"] = 203] = "NamedTupleMember"; - SyntaxKind[SyntaxKind["TemplateLiteralType"] = 204] = "TemplateLiteralType"; - SyntaxKind[SyntaxKind["TemplateLiteralTypeSpan"] = 205] = "TemplateLiteralTypeSpan"; - SyntaxKind[SyntaxKind["ImportType"] = 206] = "ImportType"; - SyntaxKind[SyntaxKind["ObjectBindingPattern"] = 207] = "ObjectBindingPattern"; - SyntaxKind[SyntaxKind["ArrayBindingPattern"] = 208] = "ArrayBindingPattern"; - SyntaxKind[SyntaxKind["BindingElement"] = 209] = "BindingElement"; - SyntaxKind[SyntaxKind["ArrayLiteralExpression"] = 210] = "ArrayLiteralExpression"; - SyntaxKind[SyntaxKind["ObjectLiteralExpression"] = 211] = "ObjectLiteralExpression"; - SyntaxKind[SyntaxKind["PropertyAccessExpression"] = 212] = "PropertyAccessExpression"; - SyntaxKind[SyntaxKind["ElementAccessExpression"] = 213] = "ElementAccessExpression"; - SyntaxKind[SyntaxKind["CallExpression"] = 214] = "CallExpression"; - SyntaxKind[SyntaxKind["NewExpression"] = 215] = "NewExpression"; - SyntaxKind[SyntaxKind["TaggedTemplateExpression"] = 216] = "TaggedTemplateExpression"; - SyntaxKind[SyntaxKind["TypeAssertionExpression"] = 217] = "TypeAssertionExpression"; - SyntaxKind[SyntaxKind["ParenthesizedExpression"] = 218] = "ParenthesizedExpression"; - SyntaxKind[SyntaxKind["FunctionExpression"] = 219] = "FunctionExpression"; - SyntaxKind[SyntaxKind["ArrowFunction"] = 220] = "ArrowFunction"; - SyntaxKind[SyntaxKind["DeleteExpression"] = 221] = "DeleteExpression"; - SyntaxKind[SyntaxKind["TypeOfExpression"] = 222] = "TypeOfExpression"; - SyntaxKind[SyntaxKind["VoidExpression"] = 223] = "VoidExpression"; - SyntaxKind[SyntaxKind["AwaitExpression"] = 224] = "AwaitExpression"; - SyntaxKind[SyntaxKind["PrefixUnaryExpression"] = 225] = "PrefixUnaryExpression"; - SyntaxKind[SyntaxKind["PostfixUnaryExpression"] = 226] = "PostfixUnaryExpression"; - SyntaxKind[SyntaxKind["BinaryExpression"] = 227] = "BinaryExpression"; - SyntaxKind[SyntaxKind["ConditionalExpression"] = 228] = "ConditionalExpression"; - SyntaxKind[SyntaxKind["TemplateExpression"] = 229] = "TemplateExpression"; - SyntaxKind[SyntaxKind["YieldExpression"] = 230] = "YieldExpression"; - SyntaxKind[SyntaxKind["SpreadElement"] = 231] = "SpreadElement"; - SyntaxKind[SyntaxKind["ClassExpression"] = 232] = "ClassExpression"; - SyntaxKind[SyntaxKind["OmittedExpression"] = 233] = "OmittedExpression"; - SyntaxKind[SyntaxKind["ExpressionWithTypeArguments"] = 234] = "ExpressionWithTypeArguments"; - SyntaxKind[SyntaxKind["AsExpression"] = 235] = "AsExpression"; - SyntaxKind[SyntaxKind["NonNullExpression"] = 236] = "NonNullExpression"; - SyntaxKind[SyntaxKind["MetaProperty"] = 237] = "MetaProperty"; - SyntaxKind[SyntaxKind["SyntheticExpression"] = 238] = "SyntheticExpression"; - SyntaxKind[SyntaxKind["SatisfiesExpression"] = 239] = "SatisfiesExpression"; - SyntaxKind[SyntaxKind["TemplateSpan"] = 240] = "TemplateSpan"; - SyntaxKind[SyntaxKind["SemicolonClassElement"] = 241] = "SemicolonClassElement"; - SyntaxKind[SyntaxKind["Block"] = 242] = "Block"; - SyntaxKind[SyntaxKind["EmptyStatement"] = 243] = "EmptyStatement"; - SyntaxKind[SyntaxKind["VariableStatement"] = 244] = "VariableStatement"; - SyntaxKind[SyntaxKind["ExpressionStatement"] = 245] = "ExpressionStatement"; - SyntaxKind[SyntaxKind["IfStatement"] = 246] = "IfStatement"; - SyntaxKind[SyntaxKind["DoStatement"] = 247] = "DoStatement"; - SyntaxKind[SyntaxKind["WhileStatement"] = 248] = "WhileStatement"; - SyntaxKind[SyntaxKind["ForStatement"] = 249] = "ForStatement"; - SyntaxKind[SyntaxKind["ForInStatement"] = 250] = "ForInStatement"; - SyntaxKind[SyntaxKind["ForOfStatement"] = 251] = "ForOfStatement"; - SyntaxKind[SyntaxKind["ContinueStatement"] = 252] = "ContinueStatement"; - SyntaxKind[SyntaxKind["BreakStatement"] = 253] = "BreakStatement"; - SyntaxKind[SyntaxKind["ReturnStatement"] = 254] = "ReturnStatement"; - SyntaxKind[SyntaxKind["WithStatement"] = 255] = "WithStatement"; - SyntaxKind[SyntaxKind["SwitchStatement"] = 256] = "SwitchStatement"; - SyntaxKind[SyntaxKind["LabeledStatement"] = 257] = "LabeledStatement"; - SyntaxKind[SyntaxKind["ThrowStatement"] = 258] = "ThrowStatement"; - SyntaxKind[SyntaxKind["TryStatement"] = 259] = "TryStatement"; - SyntaxKind[SyntaxKind["DebuggerStatement"] = 260] = "DebuggerStatement"; - SyntaxKind[SyntaxKind["VariableDeclaration"] = 261] = "VariableDeclaration"; - SyntaxKind[SyntaxKind["VariableDeclarationList"] = 262] = "VariableDeclarationList"; - SyntaxKind[SyntaxKind["FunctionDeclaration"] = 263] = "FunctionDeclaration"; - SyntaxKind[SyntaxKind["ClassDeclaration"] = 264] = "ClassDeclaration"; - SyntaxKind[SyntaxKind["InterfaceDeclaration"] = 265] = "InterfaceDeclaration"; - SyntaxKind[SyntaxKind["TypeAliasDeclaration"] = 266] = "TypeAliasDeclaration"; - SyntaxKind[SyntaxKind["EnumDeclaration"] = 267] = "EnumDeclaration"; - SyntaxKind[SyntaxKind["ModuleDeclaration"] = 268] = "ModuleDeclaration"; - SyntaxKind[SyntaxKind["ModuleBlock"] = 269] = "ModuleBlock"; - SyntaxKind[SyntaxKind["CaseBlock"] = 270] = "CaseBlock"; - SyntaxKind[SyntaxKind["NamespaceExportDeclaration"] = 271] = "NamespaceExportDeclaration"; - SyntaxKind[SyntaxKind["ImportEqualsDeclaration"] = 272] = "ImportEqualsDeclaration"; - SyntaxKind[SyntaxKind["ImportDeclaration"] = 273] = "ImportDeclaration"; - SyntaxKind[SyntaxKind["ImportClause"] = 274] = "ImportClause"; - SyntaxKind[SyntaxKind["NamespaceImport"] = 275] = "NamespaceImport"; - SyntaxKind[SyntaxKind["NamedImports"] = 276] = "NamedImports"; - SyntaxKind[SyntaxKind["ImportSpecifier"] = 277] = "ImportSpecifier"; - SyntaxKind[SyntaxKind["ExportAssignment"] = 278] = "ExportAssignment"; - SyntaxKind[SyntaxKind["ExportDeclaration"] = 279] = "ExportDeclaration"; - SyntaxKind[SyntaxKind["NamedExports"] = 280] = "NamedExports"; - SyntaxKind[SyntaxKind["NamespaceExport"] = 281] = "NamespaceExport"; - SyntaxKind[SyntaxKind["ExportSpecifier"] = 282] = "ExportSpecifier"; - SyntaxKind[SyntaxKind["MissingDeclaration"] = 283] = "MissingDeclaration"; - SyntaxKind[SyntaxKind["ExternalModuleReference"] = 284] = "ExternalModuleReference"; - SyntaxKind[SyntaxKind["JsxElement"] = 285] = "JsxElement"; - SyntaxKind[SyntaxKind["JsxSelfClosingElement"] = 286] = "JsxSelfClosingElement"; - SyntaxKind[SyntaxKind["JsxOpeningElement"] = 287] = "JsxOpeningElement"; - SyntaxKind[SyntaxKind["JsxClosingElement"] = 288] = "JsxClosingElement"; - SyntaxKind[SyntaxKind["JsxFragment"] = 289] = "JsxFragment"; - SyntaxKind[SyntaxKind["JsxOpeningFragment"] = 290] = "JsxOpeningFragment"; - SyntaxKind[SyntaxKind["JsxClosingFragment"] = 291] = "JsxClosingFragment"; - SyntaxKind[SyntaxKind["JsxAttribute"] = 292] = "JsxAttribute"; - SyntaxKind[SyntaxKind["JsxAttributes"] = 293] = "JsxAttributes"; - SyntaxKind[SyntaxKind["JsxSpreadAttribute"] = 294] = "JsxSpreadAttribute"; - SyntaxKind[SyntaxKind["JsxExpression"] = 295] = "JsxExpression"; - SyntaxKind[SyntaxKind["JsxNamespacedName"] = 296] = "JsxNamespacedName"; - SyntaxKind[SyntaxKind["CaseClause"] = 297] = "CaseClause"; - SyntaxKind[SyntaxKind["DefaultClause"] = 298] = "DefaultClause"; - SyntaxKind[SyntaxKind["HeritageClause"] = 299] = "HeritageClause"; - SyntaxKind[SyntaxKind["CatchClause"] = 300] = "CatchClause"; - SyntaxKind[SyntaxKind["ImportAttributes"] = 301] = "ImportAttributes"; - SyntaxKind[SyntaxKind["ImportAttribute"] = 302] = "ImportAttribute"; - SyntaxKind[SyntaxKind["PropertyAssignment"] = 303] = "PropertyAssignment"; - SyntaxKind[SyntaxKind["ShorthandPropertyAssignment"] = 304] = "ShorthandPropertyAssignment"; - SyntaxKind[SyntaxKind["SpreadAssignment"] = 305] = "SpreadAssignment"; - SyntaxKind[SyntaxKind["EnumMember"] = 306] = "EnumMember"; - SyntaxKind[SyntaxKind["SourceFile"] = 307] = "SourceFile"; - SyntaxKind[SyntaxKind["JSDocTypeExpression"] = 308] = "JSDocTypeExpression"; - SyntaxKind[SyntaxKind["JSDocNameReference"] = 309] = "JSDocNameReference"; - SyntaxKind[SyntaxKind["JSDocAllType"] = 310] = "JSDocAllType"; - SyntaxKind[SyntaxKind["JSDocNullableType"] = 311] = "JSDocNullableType"; - SyntaxKind[SyntaxKind["JSDocNonNullableType"] = 312] = "JSDocNonNullableType"; - SyntaxKind[SyntaxKind["JSDocOptionalType"] = 313] = "JSDocOptionalType"; - SyntaxKind[SyntaxKind["JSDocVariadicType"] = 314] = "JSDocVariadicType"; - SyntaxKind[SyntaxKind["JSDoc"] = 315] = "JSDoc"; - SyntaxKind[SyntaxKind["JSDocText"] = 316] = "JSDocText"; - SyntaxKind[SyntaxKind["JSDocTypeLiteral"] = 317] = "JSDocTypeLiteral"; - SyntaxKind[SyntaxKind["JSDocSignature"] = 318] = "JSDocSignature"; - SyntaxKind[SyntaxKind["JSDocLink"] = 319] = "JSDocLink"; - SyntaxKind[SyntaxKind["JSDocLinkCode"] = 320] = "JSDocLinkCode"; - SyntaxKind[SyntaxKind["JSDocLinkPlain"] = 321] = "JSDocLinkPlain"; - SyntaxKind[SyntaxKind["JSDocUnknownTag"] = 322] = "JSDocUnknownTag"; - SyntaxKind[SyntaxKind["JSDocAugmentsTag"] = 323] = "JSDocAugmentsTag"; - SyntaxKind[SyntaxKind["JSDocImplementsTag"] = 324] = "JSDocImplementsTag"; - SyntaxKind[SyntaxKind["JSDocDeprecatedTag"] = 325] = "JSDocDeprecatedTag"; - SyntaxKind[SyntaxKind["JSDocPublicTag"] = 326] = "JSDocPublicTag"; - SyntaxKind[SyntaxKind["JSDocPrivateTag"] = 327] = "JSDocPrivateTag"; - SyntaxKind[SyntaxKind["JSDocProtectedTag"] = 328] = "JSDocProtectedTag"; - SyntaxKind[SyntaxKind["JSDocReadonlyTag"] = 329] = "JSDocReadonlyTag"; - SyntaxKind[SyntaxKind["JSDocOverrideTag"] = 330] = "JSDocOverrideTag"; - SyntaxKind[SyntaxKind["JSDocCallbackTag"] = 331] = "JSDocCallbackTag"; - SyntaxKind[SyntaxKind["JSDocOverloadTag"] = 332] = "JSDocOverloadTag"; - SyntaxKind[SyntaxKind["JSDocParameterTag"] = 333] = "JSDocParameterTag"; - SyntaxKind[SyntaxKind["JSDocReturnTag"] = 334] = "JSDocReturnTag"; - SyntaxKind[SyntaxKind["JSDocThisTag"] = 335] = "JSDocThisTag"; - SyntaxKind[SyntaxKind["JSDocTypeTag"] = 336] = "JSDocTypeTag"; - SyntaxKind[SyntaxKind["JSDocTemplateTag"] = 337] = "JSDocTemplateTag"; - SyntaxKind[SyntaxKind["JSDocTypedefTag"] = 338] = "JSDocTypedefTag"; - SyntaxKind[SyntaxKind["JSDocSeeTag"] = 339] = "JSDocSeeTag"; - SyntaxKind[SyntaxKind["JSDocPropertyTag"] = 340] = "JSDocPropertyTag"; - SyntaxKind[SyntaxKind["JSDocThrowsTag"] = 341] = "JSDocThrowsTag"; - SyntaxKind[SyntaxKind["JSDocSatisfiesTag"] = 342] = "JSDocSatisfiesTag"; - SyntaxKind[SyntaxKind["JSDocImportTag"] = 343] = "JSDocImportTag"; - SyntaxKind[SyntaxKind["SyntaxList"] = 344] = "SyntaxList"; - SyntaxKind[SyntaxKind["JSTypeAliasDeclaration"] = 345] = "JSTypeAliasDeclaration"; - SyntaxKind[SyntaxKind["JSImportDeclaration"] = 346] = "JSImportDeclaration"; - SyntaxKind[SyntaxKind["NotEmittedStatement"] = 347] = "NotEmittedStatement"; - SyntaxKind[SyntaxKind["PartiallyEmittedExpression"] = 348] = "PartiallyEmittedExpression"; - SyntaxKind[SyntaxKind["SyntheticReferenceExpression"] = 349] = "SyntheticReferenceExpression"; - SyntaxKind[SyntaxKind["NotEmittedTypeElement"] = 350] = "NotEmittedTypeElement"; - SyntaxKind[SyntaxKind["Count"] = 351] = "Count"; + SyntaxKind[SyntaxKind["NotKeyword"] = 147] = "NotKeyword"; + SyntaxKind[SyntaxKind["OutKeyword"] = 148] = "OutKeyword"; + SyntaxKind[SyntaxKind["ReadonlyKeyword"] = 149] = "ReadonlyKeyword"; + SyntaxKind[SyntaxKind["RequireKeyword"] = 150] = "RequireKeyword"; + SyntaxKind[SyntaxKind["NumberKeyword"] = 151] = "NumberKeyword"; + SyntaxKind[SyntaxKind["ObjectKeyword"] = 152] = "ObjectKeyword"; + SyntaxKind[SyntaxKind["SatisfiesKeyword"] = 153] = "SatisfiesKeyword"; + SyntaxKind[SyntaxKind["SetKeyword"] = 154] = "SetKeyword"; + SyntaxKind[SyntaxKind["StringKeyword"] = 155] = "StringKeyword"; + SyntaxKind[SyntaxKind["SymbolKeyword"] = 156] = "SymbolKeyword"; + SyntaxKind[SyntaxKind["TypeKeyword"] = 157] = "TypeKeyword"; + SyntaxKind[SyntaxKind["UndefinedKeyword"] = 158] = "UndefinedKeyword"; + SyntaxKind[SyntaxKind["UniqueKeyword"] = 159] = "UniqueKeyword"; + SyntaxKind[SyntaxKind["UnknownKeyword"] = 160] = "UnknownKeyword"; + SyntaxKind[SyntaxKind["UsingKeyword"] = 161] = "UsingKeyword"; + SyntaxKind[SyntaxKind["FromKeyword"] = 162] = "FromKeyword"; + SyntaxKind[SyntaxKind["GlobalKeyword"] = 163] = "GlobalKeyword"; + SyntaxKind[SyntaxKind["BigIntKeyword"] = 164] = "BigIntKeyword"; + SyntaxKind[SyntaxKind["OverrideKeyword"] = 165] = "OverrideKeyword"; + SyntaxKind[SyntaxKind["OfKeyword"] = 166] = "OfKeyword"; + SyntaxKind[SyntaxKind["DeferKeyword"] = 167] = "DeferKeyword"; + SyntaxKind[SyntaxKind["QualifiedName"] = 168] = "QualifiedName"; + SyntaxKind[SyntaxKind["ComputedPropertyName"] = 169] = "ComputedPropertyName"; + SyntaxKind[SyntaxKind["TypeParameter"] = 170] = "TypeParameter"; + SyntaxKind[SyntaxKind["Parameter"] = 171] = "Parameter"; + SyntaxKind[SyntaxKind["Decorator"] = 172] = "Decorator"; + SyntaxKind[SyntaxKind["PropertySignature"] = 173] = "PropertySignature"; + SyntaxKind[SyntaxKind["PropertyDeclaration"] = 174] = "PropertyDeclaration"; + SyntaxKind[SyntaxKind["MethodSignature"] = 175] = "MethodSignature"; + SyntaxKind[SyntaxKind["MethodDeclaration"] = 176] = "MethodDeclaration"; + SyntaxKind[SyntaxKind["ClassStaticBlockDeclaration"] = 177] = "ClassStaticBlockDeclaration"; + SyntaxKind[SyntaxKind["Constructor"] = 178] = "Constructor"; + SyntaxKind[SyntaxKind["GetAccessor"] = 179] = "GetAccessor"; + SyntaxKind[SyntaxKind["SetAccessor"] = 180] = "SetAccessor"; + SyntaxKind[SyntaxKind["CallSignature"] = 181] = "CallSignature"; + SyntaxKind[SyntaxKind["ConstructSignature"] = 182] = "ConstructSignature"; + SyntaxKind[SyntaxKind["IndexSignature"] = 183] = "IndexSignature"; + SyntaxKind[SyntaxKind["TypePredicate"] = 184] = "TypePredicate"; + SyntaxKind[SyntaxKind["TypeReference"] = 185] = "TypeReference"; + SyntaxKind[SyntaxKind["FunctionType"] = 186] = "FunctionType"; + SyntaxKind[SyntaxKind["ConstructorType"] = 187] = "ConstructorType"; + SyntaxKind[SyntaxKind["TypeQuery"] = 188] = "TypeQuery"; + SyntaxKind[SyntaxKind["TypeLiteral"] = 189] = "TypeLiteral"; + SyntaxKind[SyntaxKind["ArrayType"] = 190] = "ArrayType"; + SyntaxKind[SyntaxKind["TupleType"] = 191] = "TupleType"; + SyntaxKind[SyntaxKind["OptionalType"] = 192] = "OptionalType"; + SyntaxKind[SyntaxKind["RestType"] = 193] = "RestType"; + SyntaxKind[SyntaxKind["UnionType"] = 194] = "UnionType"; + SyntaxKind[SyntaxKind["IntersectionType"] = 195] = "IntersectionType"; + SyntaxKind[SyntaxKind["ConditionalType"] = 196] = "ConditionalType"; + SyntaxKind[SyntaxKind["InferType"] = 197] = "InferType"; + SyntaxKind[SyntaxKind["ParenthesizedType"] = 198] = "ParenthesizedType"; + SyntaxKind[SyntaxKind["ThisType"] = 199] = "ThisType"; + SyntaxKind[SyntaxKind["TypeOperator"] = 200] = "TypeOperator"; + SyntaxKind[SyntaxKind["IndexedAccessType"] = 201] = "IndexedAccessType"; + SyntaxKind[SyntaxKind["MappedType"] = 202] = "MappedType"; + SyntaxKind[SyntaxKind["LiteralType"] = 203] = "LiteralType"; + SyntaxKind[SyntaxKind["NamedTupleMember"] = 204] = "NamedTupleMember"; + SyntaxKind[SyntaxKind["TemplateLiteralType"] = 205] = "TemplateLiteralType"; + SyntaxKind[SyntaxKind["TemplateLiteralTypeSpan"] = 206] = "TemplateLiteralTypeSpan"; + SyntaxKind[SyntaxKind["ImportType"] = 207] = "ImportType"; + SyntaxKind[SyntaxKind["ObjectBindingPattern"] = 208] = "ObjectBindingPattern"; + SyntaxKind[SyntaxKind["ArrayBindingPattern"] = 209] = "ArrayBindingPattern"; + SyntaxKind[SyntaxKind["BindingElement"] = 210] = "BindingElement"; + SyntaxKind[SyntaxKind["ArrayLiteralExpression"] = 211] = "ArrayLiteralExpression"; + SyntaxKind[SyntaxKind["ObjectLiteralExpression"] = 212] = "ObjectLiteralExpression"; + SyntaxKind[SyntaxKind["PropertyAccessExpression"] = 213] = "PropertyAccessExpression"; + SyntaxKind[SyntaxKind["ElementAccessExpression"] = 214] = "ElementAccessExpression"; + SyntaxKind[SyntaxKind["CallExpression"] = 215] = "CallExpression"; + SyntaxKind[SyntaxKind["NewExpression"] = 216] = "NewExpression"; + SyntaxKind[SyntaxKind["TaggedTemplateExpression"] = 217] = "TaggedTemplateExpression"; + SyntaxKind[SyntaxKind["TypeAssertionExpression"] = 218] = "TypeAssertionExpression"; + SyntaxKind[SyntaxKind["ParenthesizedExpression"] = 219] = "ParenthesizedExpression"; + SyntaxKind[SyntaxKind["FunctionExpression"] = 220] = "FunctionExpression"; + SyntaxKind[SyntaxKind["ArrowFunction"] = 221] = "ArrowFunction"; + SyntaxKind[SyntaxKind["DeleteExpression"] = 222] = "DeleteExpression"; + SyntaxKind[SyntaxKind["TypeOfExpression"] = 223] = "TypeOfExpression"; + SyntaxKind[SyntaxKind["VoidExpression"] = 224] = "VoidExpression"; + SyntaxKind[SyntaxKind["AwaitExpression"] = 225] = "AwaitExpression"; + SyntaxKind[SyntaxKind["PrefixUnaryExpression"] = 226] = "PrefixUnaryExpression"; + SyntaxKind[SyntaxKind["PostfixUnaryExpression"] = 227] = "PostfixUnaryExpression"; + SyntaxKind[SyntaxKind["BinaryExpression"] = 228] = "BinaryExpression"; + SyntaxKind[SyntaxKind["ConditionalExpression"] = 229] = "ConditionalExpression"; + SyntaxKind[SyntaxKind["TemplateExpression"] = 230] = "TemplateExpression"; + SyntaxKind[SyntaxKind["YieldExpression"] = 231] = "YieldExpression"; + SyntaxKind[SyntaxKind["SpreadElement"] = 232] = "SpreadElement"; + SyntaxKind[SyntaxKind["ClassExpression"] = 233] = "ClassExpression"; + SyntaxKind[SyntaxKind["OmittedExpression"] = 234] = "OmittedExpression"; + SyntaxKind[SyntaxKind["ExpressionWithTypeArguments"] = 235] = "ExpressionWithTypeArguments"; + SyntaxKind[SyntaxKind["AsExpression"] = 236] = "AsExpression"; + SyntaxKind[SyntaxKind["NonNullExpression"] = 237] = "NonNullExpression"; + SyntaxKind[SyntaxKind["MetaProperty"] = 238] = "MetaProperty"; + SyntaxKind[SyntaxKind["SyntheticExpression"] = 239] = "SyntheticExpression"; + SyntaxKind[SyntaxKind["SatisfiesExpression"] = 240] = "SatisfiesExpression"; + SyntaxKind[SyntaxKind["TemplateSpan"] = 241] = "TemplateSpan"; + SyntaxKind[SyntaxKind["SemicolonClassElement"] = 242] = "SemicolonClassElement"; + SyntaxKind[SyntaxKind["Block"] = 243] = "Block"; + SyntaxKind[SyntaxKind["EmptyStatement"] = 244] = "EmptyStatement"; + SyntaxKind[SyntaxKind["VariableStatement"] = 245] = "VariableStatement"; + SyntaxKind[SyntaxKind["ExpressionStatement"] = 246] = "ExpressionStatement"; + SyntaxKind[SyntaxKind["IfStatement"] = 247] = "IfStatement"; + SyntaxKind[SyntaxKind["DoStatement"] = 248] = "DoStatement"; + SyntaxKind[SyntaxKind["WhileStatement"] = 249] = "WhileStatement"; + SyntaxKind[SyntaxKind["ForStatement"] = 250] = "ForStatement"; + SyntaxKind[SyntaxKind["ForInStatement"] = 251] = "ForInStatement"; + SyntaxKind[SyntaxKind["ForOfStatement"] = 252] = "ForOfStatement"; + SyntaxKind[SyntaxKind["ContinueStatement"] = 253] = "ContinueStatement"; + SyntaxKind[SyntaxKind["BreakStatement"] = 254] = "BreakStatement"; + SyntaxKind[SyntaxKind["ReturnStatement"] = 255] = "ReturnStatement"; + SyntaxKind[SyntaxKind["WithStatement"] = 256] = "WithStatement"; + SyntaxKind[SyntaxKind["SwitchStatement"] = 257] = "SwitchStatement"; + SyntaxKind[SyntaxKind["LabeledStatement"] = 258] = "LabeledStatement"; + SyntaxKind[SyntaxKind["ThrowStatement"] = 259] = "ThrowStatement"; + SyntaxKind[SyntaxKind["TryStatement"] = 260] = "TryStatement"; + SyntaxKind[SyntaxKind["DebuggerStatement"] = 261] = "DebuggerStatement"; + SyntaxKind[SyntaxKind["VariableDeclaration"] = 262] = "VariableDeclaration"; + SyntaxKind[SyntaxKind["VariableDeclarationList"] = 263] = "VariableDeclarationList"; + SyntaxKind[SyntaxKind["FunctionDeclaration"] = 264] = "FunctionDeclaration"; + SyntaxKind[SyntaxKind["ClassDeclaration"] = 265] = "ClassDeclaration"; + SyntaxKind[SyntaxKind["InterfaceDeclaration"] = 266] = "InterfaceDeclaration"; + SyntaxKind[SyntaxKind["TypeAliasDeclaration"] = 267] = "TypeAliasDeclaration"; + SyntaxKind[SyntaxKind["EnumDeclaration"] = 268] = "EnumDeclaration"; + SyntaxKind[SyntaxKind["ModuleDeclaration"] = 269] = "ModuleDeclaration"; + SyntaxKind[SyntaxKind["ModuleBlock"] = 270] = "ModuleBlock"; + SyntaxKind[SyntaxKind["CaseBlock"] = 271] = "CaseBlock"; + SyntaxKind[SyntaxKind["NamespaceExportDeclaration"] = 272] = "NamespaceExportDeclaration"; + SyntaxKind[SyntaxKind["ImportEqualsDeclaration"] = 273] = "ImportEqualsDeclaration"; + SyntaxKind[SyntaxKind["ImportDeclaration"] = 274] = "ImportDeclaration"; + SyntaxKind[SyntaxKind["ImportClause"] = 275] = "ImportClause"; + SyntaxKind[SyntaxKind["NamespaceImport"] = 276] = "NamespaceImport"; + SyntaxKind[SyntaxKind["NamedImports"] = 277] = "NamedImports"; + SyntaxKind[SyntaxKind["ImportSpecifier"] = 278] = "ImportSpecifier"; + SyntaxKind[SyntaxKind["ExportAssignment"] = 279] = "ExportAssignment"; + SyntaxKind[SyntaxKind["ExportDeclaration"] = 280] = "ExportDeclaration"; + SyntaxKind[SyntaxKind["NamedExports"] = 281] = "NamedExports"; + SyntaxKind[SyntaxKind["NamespaceExport"] = 282] = "NamespaceExport"; + SyntaxKind[SyntaxKind["ExportSpecifier"] = 283] = "ExportSpecifier"; + SyntaxKind[SyntaxKind["MissingDeclaration"] = 284] = "MissingDeclaration"; + SyntaxKind[SyntaxKind["ExternalModuleReference"] = 285] = "ExternalModuleReference"; + SyntaxKind[SyntaxKind["JsxElement"] = 286] = "JsxElement"; + SyntaxKind[SyntaxKind["JsxSelfClosingElement"] = 287] = "JsxSelfClosingElement"; + SyntaxKind[SyntaxKind["JsxOpeningElement"] = 288] = "JsxOpeningElement"; + SyntaxKind[SyntaxKind["JsxClosingElement"] = 289] = "JsxClosingElement"; + SyntaxKind[SyntaxKind["JsxFragment"] = 290] = "JsxFragment"; + SyntaxKind[SyntaxKind["JsxOpeningFragment"] = 291] = "JsxOpeningFragment"; + SyntaxKind[SyntaxKind["JsxClosingFragment"] = 292] = "JsxClosingFragment"; + SyntaxKind[SyntaxKind["JsxAttribute"] = 293] = "JsxAttribute"; + SyntaxKind[SyntaxKind["JsxAttributes"] = 294] = "JsxAttributes"; + SyntaxKind[SyntaxKind["JsxSpreadAttribute"] = 295] = "JsxSpreadAttribute"; + SyntaxKind[SyntaxKind["JsxExpression"] = 296] = "JsxExpression"; + SyntaxKind[SyntaxKind["JsxNamespacedName"] = 297] = "JsxNamespacedName"; + SyntaxKind[SyntaxKind["CaseClause"] = 298] = "CaseClause"; + SyntaxKind[SyntaxKind["DefaultClause"] = 299] = "DefaultClause"; + SyntaxKind[SyntaxKind["HeritageClause"] = 300] = "HeritageClause"; + SyntaxKind[SyntaxKind["CatchClause"] = 301] = "CatchClause"; + SyntaxKind[SyntaxKind["ImportAttributes"] = 302] = "ImportAttributes"; + SyntaxKind[SyntaxKind["ImportAttribute"] = 303] = "ImportAttribute"; + SyntaxKind[SyntaxKind["PropertyAssignment"] = 304] = "PropertyAssignment"; + SyntaxKind[SyntaxKind["ShorthandPropertyAssignment"] = 305] = "ShorthandPropertyAssignment"; + SyntaxKind[SyntaxKind["SpreadAssignment"] = 306] = "SpreadAssignment"; + SyntaxKind[SyntaxKind["EnumMember"] = 307] = "EnumMember"; + SyntaxKind[SyntaxKind["SourceFile"] = 308] = "SourceFile"; + SyntaxKind[SyntaxKind["JSDocTypeExpression"] = 309] = "JSDocTypeExpression"; + SyntaxKind[SyntaxKind["JSDocNameReference"] = 310] = "JSDocNameReference"; + SyntaxKind[SyntaxKind["JSDocAllType"] = 311] = "JSDocAllType"; + SyntaxKind[SyntaxKind["JSDocNullableType"] = 312] = "JSDocNullableType"; + SyntaxKind[SyntaxKind["JSDocNonNullableType"] = 313] = "JSDocNonNullableType"; + SyntaxKind[SyntaxKind["JSDocOptionalType"] = 314] = "JSDocOptionalType"; + SyntaxKind[SyntaxKind["JSDocVariadicType"] = 315] = "JSDocVariadicType"; + SyntaxKind[SyntaxKind["JSDoc"] = 316] = "JSDoc"; + SyntaxKind[SyntaxKind["JSDocText"] = 317] = "JSDocText"; + SyntaxKind[SyntaxKind["JSDocTypeLiteral"] = 318] = "JSDocTypeLiteral"; + SyntaxKind[SyntaxKind["JSDocSignature"] = 319] = "JSDocSignature"; + SyntaxKind[SyntaxKind["JSDocLink"] = 320] = "JSDocLink"; + SyntaxKind[SyntaxKind["JSDocLinkCode"] = 321] = "JSDocLinkCode"; + SyntaxKind[SyntaxKind["JSDocLinkPlain"] = 322] = "JSDocLinkPlain"; + SyntaxKind[SyntaxKind["JSDocUnknownTag"] = 323] = "JSDocUnknownTag"; + SyntaxKind[SyntaxKind["JSDocAugmentsTag"] = 324] = "JSDocAugmentsTag"; + SyntaxKind[SyntaxKind["JSDocImplementsTag"] = 325] = "JSDocImplementsTag"; + SyntaxKind[SyntaxKind["JSDocDeprecatedTag"] = 326] = "JSDocDeprecatedTag"; + SyntaxKind[SyntaxKind["JSDocPublicTag"] = 327] = "JSDocPublicTag"; + SyntaxKind[SyntaxKind["JSDocPrivateTag"] = 328] = "JSDocPrivateTag"; + SyntaxKind[SyntaxKind["JSDocProtectedTag"] = 329] = "JSDocProtectedTag"; + SyntaxKind[SyntaxKind["JSDocReadonlyTag"] = 330] = "JSDocReadonlyTag"; + SyntaxKind[SyntaxKind["JSDocOverrideTag"] = 331] = "JSDocOverrideTag"; + SyntaxKind[SyntaxKind["JSDocCallbackTag"] = 332] = "JSDocCallbackTag"; + SyntaxKind[SyntaxKind["JSDocOverloadTag"] = 333] = "JSDocOverloadTag"; + SyntaxKind[SyntaxKind["JSDocParameterTag"] = 334] = "JSDocParameterTag"; + SyntaxKind[SyntaxKind["JSDocReturnTag"] = 335] = "JSDocReturnTag"; + SyntaxKind[SyntaxKind["JSDocThisTag"] = 336] = "JSDocThisTag"; + SyntaxKind[SyntaxKind["JSDocTypeTag"] = 337] = "JSDocTypeTag"; + SyntaxKind[SyntaxKind["JSDocTemplateTag"] = 338] = "JSDocTemplateTag"; + SyntaxKind[SyntaxKind["JSDocTypedefTag"] = 339] = "JSDocTypedefTag"; + SyntaxKind[SyntaxKind["JSDocSeeTag"] = 340] = "JSDocSeeTag"; + SyntaxKind[SyntaxKind["JSDocPropertyTag"] = 341] = "JSDocPropertyTag"; + SyntaxKind[SyntaxKind["JSDocThrowsTag"] = 342] = "JSDocThrowsTag"; + SyntaxKind[SyntaxKind["JSDocSatisfiesTag"] = 343] = "JSDocSatisfiesTag"; + SyntaxKind[SyntaxKind["JSDocImportTag"] = 344] = "JSDocImportTag"; + SyntaxKind[SyntaxKind["SyntaxList"] = 345] = "SyntaxList"; + SyntaxKind[SyntaxKind["JSTypeAliasDeclaration"] = 346] = "JSTypeAliasDeclaration"; + SyntaxKind[SyntaxKind["JSImportDeclaration"] = 347] = "JSImportDeclaration"; + SyntaxKind[SyntaxKind["NotEmittedStatement"] = 348] = "NotEmittedStatement"; + SyntaxKind[SyntaxKind["PartiallyEmittedExpression"] = 349] = "PartiallyEmittedExpression"; + SyntaxKind[SyntaxKind["SyntheticReferenceExpression"] = 350] = "SyntheticReferenceExpression"; + SyntaxKind[SyntaxKind["NotEmittedTypeElement"] = 351] = "NotEmittedTypeElement"; + SyntaxKind[SyntaxKind["Count"] = 352] = "Count"; SyntaxKind[SyntaxKind["FirstAssignment"] = 63] = "FirstAssignment"; SyntaxKind[SyntaxKind["LastAssignment"] = 78] = "LastAssignment"; SyntaxKind[SyntaxKind["FirstCompoundAssignment"] = 64] = "FirstCompoundAssignment"; @@ -360,30 +361,30 @@ export var SyntaxKind: any; SyntaxKind[SyntaxKind["FirstReservedWord"] = 82] = "FirstReservedWord"; SyntaxKind[SyntaxKind["LastReservedWord"] = 117] = "LastReservedWord"; SyntaxKind[SyntaxKind["FirstKeyword"] = 82] = "FirstKeyword"; - SyntaxKind[SyntaxKind["LastKeyword"] = 166] = "LastKeyword"; + SyntaxKind[SyntaxKind["LastKeyword"] = 167] = "LastKeyword"; SyntaxKind[SyntaxKind["FirstFutureReservedWord"] = 118] = "FirstFutureReservedWord"; SyntaxKind[SyntaxKind["LastFutureReservedWord"] = 126] = "LastFutureReservedWord"; - SyntaxKind[SyntaxKind["FirstTypeNode"] = 183] = "FirstTypeNode"; - SyntaxKind[SyntaxKind["LastTypeNode"] = 206] = "LastTypeNode"; + SyntaxKind[SyntaxKind["FirstTypeNode"] = 184] = "FirstTypeNode"; + SyntaxKind[SyntaxKind["LastTypeNode"] = 207] = "LastTypeNode"; SyntaxKind[SyntaxKind["FirstPunctuation"] = 18] = "FirstPunctuation"; SyntaxKind[SyntaxKind["LastPunctuation"] = 78] = "LastPunctuation"; SyntaxKind[SyntaxKind["FirstToken"] = 0] = "FirstToken"; - SyntaxKind[SyntaxKind["LastToken"] = 166] = "LastToken"; + SyntaxKind[SyntaxKind["LastToken"] = 167] = "LastToken"; SyntaxKind[SyntaxKind["FirstLiteralToken"] = 8] = "FirstLiteralToken"; SyntaxKind[SyntaxKind["LastLiteralToken"] = 14] = "LastLiteralToken"; SyntaxKind[SyntaxKind["FirstTemplateToken"] = 14] = "FirstTemplateToken"; SyntaxKind[SyntaxKind["LastTemplateToken"] = 17] = "LastTemplateToken"; SyntaxKind[SyntaxKind["FirstBinaryOperator"] = 29] = "FirstBinaryOperator"; SyntaxKind[SyntaxKind["LastBinaryOperator"] = 78] = "LastBinaryOperator"; - SyntaxKind[SyntaxKind["FirstStatement"] = 244] = "FirstStatement"; - SyntaxKind[SyntaxKind["LastStatement"] = 260] = "LastStatement"; - SyntaxKind[SyntaxKind["FirstNode"] = 167] = "FirstNode"; - SyntaxKind[SyntaxKind["FirstJSDocNode"] = 308] = "FirstJSDocNode"; - SyntaxKind[SyntaxKind["LastJSDocNode"] = 343] = "LastJSDocNode"; - SyntaxKind[SyntaxKind["FirstJSDocTagNode"] = 322] = "FirstJSDocTagNode"; - SyntaxKind[SyntaxKind["LastJSDocTagNode"] = 343] = "LastJSDocTagNode"; + SyntaxKind[SyntaxKind["FirstStatement"] = 245] = "FirstStatement"; + SyntaxKind[SyntaxKind["LastStatement"] = 261] = "LastStatement"; + SyntaxKind[SyntaxKind["FirstNode"] = 168] = "FirstNode"; + SyntaxKind[SyntaxKind["FirstJSDocNode"] = 309] = "FirstJSDocNode"; + SyntaxKind[SyntaxKind["LastJSDocNode"] = 344] = "LastJSDocNode"; + SyntaxKind[SyntaxKind["FirstJSDocTagNode"] = 323] = "FirstJSDocTagNode"; + SyntaxKind[SyntaxKind["LastJSDocTagNode"] = 344] = "LastJSDocTagNode"; SyntaxKind[SyntaxKind["FirstContextualKeyword"] = 127] = "FirstContextualKeyword"; - SyntaxKind[SyntaxKind["LastContextualKeyword"] = 166] = "LastContextualKeyword"; + SyntaxKind[SyntaxKind["LastContextualKeyword"] = 167] = "LastContextualKeyword"; SyntaxKind[SyntaxKind["LastUnaryOperator"] = 54] = "LastUnaryOperator"; SyntaxKind[SyntaxKind["FirstTriviaToken"] = 2] = "FirstTriviaToken"; SyntaxKind[SyntaxKind["LastTriviaToken"] = 6] = "LastTriviaToken"; diff --git a/packages/typescript/src/enums/typeFlags.enum.ts b/packages/typescript/src/enums/typeFlags.enum.ts index 88701e2174f55..2ed6e3f301db6 100644 --- a/packages/typescript/src/enums/typeFlags.enum.ts +++ b/packages/typescript/src/enums/typeFlags.enum.ts @@ -27,13 +27,11 @@ export enum TypeFlags { TemplateLiteral = 1 << 22, StringMapping = 1 << 23, Substitution = 1 << 24, - IndexedAccess = 1 << 25, - Conditional = 1 << 26, - Union = 1 << 27, - Intersection = 1 << 28, - Reserved1 = 1 << 29, - Reserved2 = 1 << 30, - Reserved3 = 1 << 31, + Negated = 1 << 25, + IndexedAccess = 1 << 26, + Conditional = 1 << 27, + Union = 1 << 28, + Intersection = 1 << 29, AnyOrUnknown = Any | Unknown, Nullable = Undefined | Null, Literal = StringLiteral | NumberLiteral | BigIntLiteral | BooleanLiteral, @@ -57,7 +55,7 @@ export enum TypeFlags { UnionOrIntersection = Union | Intersection, StructuredType = Object | Union | Intersection, TypeVariable = TypeParameter | IndexedAccess, - InstantiableNonPrimitive = TypeVariable | Conditional | Substitution, + InstantiableNonPrimitive = TypeVariable | Conditional | Substitution | Negated, InstantiablePrimitive = Index | TemplateLiteral | StringMapping, Instantiable = InstantiableNonPrimitive | InstantiablePrimitive, StructuredOrInstantiable = StructuredType | Instantiable, @@ -71,7 +69,5 @@ export enum TypeFlags { IncludesWildcard = IndexedAccess, IncludesEmptyObject = Conditional, IncludesInstantiable = Substitution, - IncludesConstrainedTypeVariable = Reserved1, - IncludesError = Reserved2, NotPrimitiveUnion = Any | Unknown | Void | Never | Object | Intersection | IncludesInstantiable, } diff --git a/packages/typescript/src/enums/typeFlags.ts b/packages/typescript/src/enums/typeFlags.ts index 01fbbcbdeaca5..d3d49ba365786 100644 --- a/packages/typescript/src/enums/typeFlags.ts +++ b/packages/typescript/src/enums/typeFlags.ts @@ -27,13 +27,11 @@ export var TypeFlags: any; TypeFlags[TypeFlags["TemplateLiteral"] = 4194304] = "TemplateLiteral"; TypeFlags[TypeFlags["StringMapping"] = 8388608] = "StringMapping"; TypeFlags[TypeFlags["Substitution"] = 16777216] = "Substitution"; - TypeFlags[TypeFlags["IndexedAccess"] = 33554432] = "IndexedAccess"; - TypeFlags[TypeFlags["Conditional"] = 67108864] = "Conditional"; - TypeFlags[TypeFlags["Union"] = 134217728] = "Union"; - TypeFlags[TypeFlags["Intersection"] = 268435456] = "Intersection"; - TypeFlags[TypeFlags["Reserved1"] = 536870912] = "Reserved1"; - TypeFlags[TypeFlags["Reserved2"] = 1073741824] = "Reserved2"; - TypeFlags[TypeFlags["Reserved3"] = -2147483648] = "Reserved3"; + TypeFlags[TypeFlags["Negated"] = 33554432] = "Negated"; + TypeFlags[TypeFlags["IndexedAccess"] = 67108864] = "IndexedAccess"; + TypeFlags[TypeFlags["Conditional"] = 134217728] = "Conditional"; + TypeFlags[TypeFlags["Union"] = 268435456] = "Union"; + TypeFlags[TypeFlags["Intersection"] = 536870912] = "Intersection"; TypeFlags[TypeFlags["AnyOrUnknown"] = 3] = "AnyOrUnknown"; TypeFlags[TypeFlags["Nullable"] = 12] = "Nullable"; TypeFlags[TypeFlags["Literal"] = 15360] = "Literal"; @@ -54,24 +52,22 @@ export var TypeFlags: any; TypeFlags[TypeFlags["Primitive"] = 12713980] = "Primitive"; TypeFlags[TypeFlags["DefinitelyNonNullable"] = 13893600] = "DefinitelyNonNullable"; TypeFlags[TypeFlags["DisjointDomains"] = 12812284] = "DisjointDomains"; - TypeFlags[TypeFlags["UnionOrIntersection"] = 402653184] = "UnionOrIntersection"; - TypeFlags[TypeFlags["StructuredType"] = 403701760] = "StructuredType"; - TypeFlags[TypeFlags["TypeVariable"] = 34078720] = "TypeVariable"; - TypeFlags[TypeFlags["InstantiableNonPrimitive"] = 117964800] = "InstantiableNonPrimitive"; + TypeFlags[TypeFlags["UnionOrIntersection"] = 805306368] = "UnionOrIntersection"; + TypeFlags[TypeFlags["StructuredType"] = 806354944] = "StructuredType"; + TypeFlags[TypeFlags["TypeVariable"] = 67633152] = "TypeVariable"; + TypeFlags[TypeFlags["InstantiableNonPrimitive"] = 252182528] = "InstantiableNonPrimitive"; TypeFlags[TypeFlags["InstantiablePrimitive"] = 14680064] = "InstantiablePrimitive"; - TypeFlags[TypeFlags["Instantiable"] = 132644864] = "Instantiable"; - TypeFlags[TypeFlags["StructuredOrInstantiable"] = 536346624] = "StructuredOrInstantiable"; - TypeFlags[TypeFlags["ObjectFlagsType"] = 403963917] = "ObjectFlagsType"; - TypeFlags[TypeFlags["Simplifiable"] = 102760448] = "Simplifiable"; + TypeFlags[TypeFlags["Instantiable"] = 266862592] = "Instantiable"; + TypeFlags[TypeFlags["StructuredOrInstantiable"] = 1073217536] = "StructuredOrInstantiable"; + TypeFlags[TypeFlags["ObjectFlagsType"] = 806617101] = "ObjectFlagsType"; + TypeFlags[TypeFlags["Simplifiable"] = 203423744] = "Simplifiable"; TypeFlags[TypeFlags["Singleton"] = 394239] = "Singleton"; - TypeFlags[TypeFlags["Narrowable"] = 536575971] = "Narrowable"; - TypeFlags[TypeFlags["IncludesMask"] = 416808959] = "IncludesMask"; + TypeFlags[TypeFlags["Narrowable"] = 1073446883] = "Narrowable"; + TypeFlags[TypeFlags["IncludesMask"] = 819462143] = "IncludesMask"; TypeFlags[TypeFlags["IncludesMissingType"] = 524288] = "IncludesMissingType"; TypeFlags[TypeFlags["IncludesNonWideningType"] = 2097152] = "IncludesNonWideningType"; - TypeFlags[TypeFlags["IncludesWildcard"] = 33554432] = "IncludesWildcard"; - TypeFlags[TypeFlags["IncludesEmptyObject"] = 67108864] = "IncludesEmptyObject"; + TypeFlags[TypeFlags["IncludesWildcard"] = 67108864] = "IncludesWildcard"; + TypeFlags[TypeFlags["IncludesEmptyObject"] = 134217728] = "IncludesEmptyObject"; TypeFlags[TypeFlags["IncludesInstantiable"] = 16777216] = "IncludesInstantiable"; - TypeFlags[TypeFlags["IncludesConstrainedTypeVariable"] = 536870912] = "IncludesConstrainedTypeVariable"; - TypeFlags[TypeFlags["IncludesError"] = 1073741824] = "IncludesError"; - TypeFlags[TypeFlags["NotPrimitiveUnion"] = 286523411] = "NotPrimitiveUnion"; + TypeFlags[TypeFlags["NotPrimitiveUnion"] = 554958867] = "NotPrimitiveUnion"; })(TypeFlags || (TypeFlags = {})); diff --git a/tools/scripts/tsc/ast.json b/tools/scripts/tsc/ast.json index 3c85511b463db..e826a212e18e9 100644 --- a/tools/scripts/tsc/ast.json +++ b/tools/scripts/tsc/ast.json @@ -176,6 +176,7 @@ "ModuleKeyword", "NamespaceKeyword", "NeverKeyword", + "NotKeyword", "OutKeyword", "ReadonlyKeyword", "RequireKeyword", @@ -3547,7 +3548,8 @@ "type": [ "SyntaxKind.KeyOfKeyword", "SyntaxKind.ReadonlyKeyword", - "SyntaxKind.UniqueKeyword" + "SyntaxKind.UniqueKeyword", + "SyntaxKind.NotKeyword" ] }, { diff --git a/tsc/internal/api/encoder/decoder_generated.go b/tsc/internal/api/encoder/decoder_generated.go index 6532a5a36ee05..008023f9bfdcc 100644 --- a/tsc/internal/api/encoder/decoder_generated.go +++ b/tsc/internal/api/encoder/decoder_generated.go @@ -198,6 +198,7 @@ func (d *astDecoder) createChildrenNode(kind ast.Kind, data uint32, childIndices ast.KindKeyOfKeyword, ast.KindModuleKeyword, ast.KindNamespaceKeyword, + ast.KindNotKeyword, ast.KindOutKeyword, ast.KindReadonlyKeyword, ast.KindRequireKeyword, @@ -750,6 +751,8 @@ func (d *astDecoder) createChildrenNode(kind ast.Kind, data uint32, childIndices operator = ast.KindReadonlyKeyword case 2: operator = ast.KindUniqueKeyword + case 3: + operator = ast.KindNotKeyword } return d.factory.NewTypeOperatorNode(operator, d.singleChild(childIndices)), nil case ast.KindInferType: diff --git a/tsc/internal/api/encoder/encoder_generated.go b/tsc/internal/api/encoder/encoder_generated.go index d3e7599e326c7..b9f2053dab309 100644 --- a/tsc/internal/api/encoder/encoder_generated.go +++ b/tsc/internal/api/encoder/encoder_generated.go @@ -603,6 +603,8 @@ func getNodeCommonData(node *ast.Node) uint32 { operatorIdx = 1 case ast.KindUniqueKeyword: operatorIdx = 2 + case ast.KindNotKeyword: + operatorIdx = 3 } return operatorIdx << 24 case ast.KindImportAttributes: diff --git a/tsc/internal/ast/ast_generated.go b/tsc/internal/ast/ast_generated.go index 87c1e59f8653e..52abd0287cfdd 100644 --- a/tsc/internal/ast/ast_generated.go +++ b/tsc/internal/ast/ast_generated.go @@ -608,7 +608,7 @@ func (node *Token) Clone(f NodeFactoryCoercible) *Node { func IsToken(node *Node) bool { switch node.Kind { - case KindUnknown, KindEndOfFile, KindSingleLineCommentTrivia, KindMultiLineCommentTrivia, KindNewLineTrivia, KindWhitespaceTrivia, KindConflictMarkerTrivia, KindNonTextFileMarkerTrivia, KindNumericLiteral, KindBigIntLiteral, KindStringLiteral, KindJsxText, KindJsxTextAllWhiteSpaces, KindRegularExpressionLiteral, KindNoSubstitutionTemplateLiteral, KindTemplateHead, KindTemplateMiddle, KindTemplateTail, KindOpenBraceToken, KindCloseBraceToken, KindOpenParenToken, KindCloseParenToken, KindOpenBracketToken, KindCloseBracketToken, KindDotToken, KindDotDotDotToken, KindSemicolonToken, KindCommaToken, KindQuestionDotToken, KindLessThanToken, KindLessThanSlashToken, KindGreaterThanToken, KindLessThanEqualsToken, KindGreaterThanEqualsToken, KindEqualsEqualsToken, KindExclamationEqualsToken, KindEqualsEqualsEqualsToken, KindExclamationEqualsEqualsToken, KindEqualsGreaterThanToken, KindPlusToken, KindMinusToken, KindAsteriskToken, KindAsteriskAsteriskToken, KindSlashToken, KindPercentToken, KindPlusPlusToken, KindMinusMinusToken, KindLessThanLessThanToken, KindGreaterThanGreaterThanToken, KindGreaterThanGreaterThanGreaterThanToken, KindAmpersandToken, KindBarToken, KindCaretToken, KindExclamationToken, KindTildeToken, KindAmpersandAmpersandToken, KindBarBarToken, KindQuestionToken, KindColonToken, KindAtToken, KindQuestionQuestionToken, KindBacktickToken, KindHashToken, KindEqualsToken, KindPlusEqualsToken, KindMinusEqualsToken, KindAsteriskEqualsToken, KindAsteriskAsteriskEqualsToken, KindSlashEqualsToken, KindPercentEqualsToken, KindLessThanLessThanEqualsToken, KindGreaterThanGreaterThanEqualsToken, KindGreaterThanGreaterThanGreaterThanEqualsToken, KindAmpersandEqualsToken, KindBarEqualsToken, KindBarBarEqualsToken, KindAmpersandAmpersandEqualsToken, KindQuestionQuestionEqualsToken, KindCaretEqualsToken, KindIdentifier, KindPrivateIdentifier, KindJSDocCommentTextToken, KindBreakKeyword, KindCaseKeyword, KindCatchKeyword, KindClassKeyword, KindConstKeyword, KindContinueKeyword, KindDebuggerKeyword, KindDefaultKeyword, KindDeleteKeyword, KindDoKeyword, KindElseKeyword, KindEnumKeyword, KindExportKeyword, KindExtendsKeyword, KindFalseKeyword, KindFinallyKeyword, KindForKeyword, KindFunctionKeyword, KindIfKeyword, KindImportKeyword, KindInKeyword, KindInstanceOfKeyword, KindNewKeyword, KindNullKeyword, KindReturnKeyword, KindSuperKeyword, KindSwitchKeyword, KindThisKeyword, KindThrowKeyword, KindTrueKeyword, KindTryKeyword, KindTypeOfKeyword, KindVarKeyword, KindVoidKeyword, KindWhileKeyword, KindWithKeyword, KindImplementsKeyword, KindInterfaceKeyword, KindLetKeyword, KindPackageKeyword, KindPrivateKeyword, KindProtectedKeyword, KindPublicKeyword, KindStaticKeyword, KindYieldKeyword, KindAbstractKeyword, KindAccessorKeyword, KindAsKeyword, KindAssertsKeyword, KindAssertKeyword, KindAnyKeyword, KindAsyncKeyword, KindAwaitKeyword, KindBooleanKeyword, KindConstructorKeyword, KindDeclareKeyword, KindGetKeyword, KindImmediateKeyword, KindInferKeyword, KindIntrinsicKeyword, KindIsKeyword, KindKeyOfKeyword, KindModuleKeyword, KindNamespaceKeyword, KindNeverKeyword, KindOutKeyword, KindReadonlyKeyword, KindRequireKeyword, KindNumberKeyword, KindObjectKeyword, KindSatisfiesKeyword, KindSetKeyword, KindStringKeyword, KindSymbolKeyword, KindTypeKeyword, KindUndefinedKeyword, KindUniqueKeyword, KindUnknownKeyword, KindUsingKeyword, KindFromKeyword, KindGlobalKeyword, KindBigIntKeyword, KindOverrideKeyword, KindOfKeyword, KindDeferKeyword: + case KindUnknown, KindEndOfFile, KindSingleLineCommentTrivia, KindMultiLineCommentTrivia, KindNewLineTrivia, KindWhitespaceTrivia, KindConflictMarkerTrivia, KindNonTextFileMarkerTrivia, KindNumericLiteral, KindBigIntLiteral, KindStringLiteral, KindJsxText, KindJsxTextAllWhiteSpaces, KindRegularExpressionLiteral, KindNoSubstitutionTemplateLiteral, KindTemplateHead, KindTemplateMiddle, KindTemplateTail, KindOpenBraceToken, KindCloseBraceToken, KindOpenParenToken, KindCloseParenToken, KindOpenBracketToken, KindCloseBracketToken, KindDotToken, KindDotDotDotToken, KindSemicolonToken, KindCommaToken, KindQuestionDotToken, KindLessThanToken, KindLessThanSlashToken, KindGreaterThanToken, KindLessThanEqualsToken, KindGreaterThanEqualsToken, KindEqualsEqualsToken, KindExclamationEqualsToken, KindEqualsEqualsEqualsToken, KindExclamationEqualsEqualsToken, KindEqualsGreaterThanToken, KindPlusToken, KindMinusToken, KindAsteriskToken, KindAsteriskAsteriskToken, KindSlashToken, KindPercentToken, KindPlusPlusToken, KindMinusMinusToken, KindLessThanLessThanToken, KindGreaterThanGreaterThanToken, KindGreaterThanGreaterThanGreaterThanToken, KindAmpersandToken, KindBarToken, KindCaretToken, KindExclamationToken, KindTildeToken, KindAmpersandAmpersandToken, KindBarBarToken, KindQuestionToken, KindColonToken, KindAtToken, KindQuestionQuestionToken, KindBacktickToken, KindHashToken, KindEqualsToken, KindPlusEqualsToken, KindMinusEqualsToken, KindAsteriskEqualsToken, KindAsteriskAsteriskEqualsToken, KindSlashEqualsToken, KindPercentEqualsToken, KindLessThanLessThanEqualsToken, KindGreaterThanGreaterThanEqualsToken, KindGreaterThanGreaterThanGreaterThanEqualsToken, KindAmpersandEqualsToken, KindBarEqualsToken, KindBarBarEqualsToken, KindAmpersandAmpersandEqualsToken, KindQuestionQuestionEqualsToken, KindCaretEqualsToken, KindIdentifier, KindPrivateIdentifier, KindJSDocCommentTextToken, KindBreakKeyword, KindCaseKeyword, KindCatchKeyword, KindClassKeyword, KindConstKeyword, KindContinueKeyword, KindDebuggerKeyword, KindDefaultKeyword, KindDeleteKeyword, KindDoKeyword, KindElseKeyword, KindEnumKeyword, KindExportKeyword, KindExtendsKeyword, KindFalseKeyword, KindFinallyKeyword, KindForKeyword, KindFunctionKeyword, KindIfKeyword, KindImportKeyword, KindInKeyword, KindInstanceOfKeyword, KindNewKeyword, KindNullKeyword, KindReturnKeyword, KindSuperKeyword, KindSwitchKeyword, KindThisKeyword, KindThrowKeyword, KindTrueKeyword, KindTryKeyword, KindTypeOfKeyword, KindVarKeyword, KindVoidKeyword, KindWhileKeyword, KindWithKeyword, KindImplementsKeyword, KindInterfaceKeyword, KindLetKeyword, KindPackageKeyword, KindPrivateKeyword, KindProtectedKeyword, KindPublicKeyword, KindStaticKeyword, KindYieldKeyword, KindAbstractKeyword, KindAccessorKeyword, KindAsKeyword, KindAssertsKeyword, KindAssertKeyword, KindAnyKeyword, KindAsyncKeyword, KindAwaitKeyword, KindBooleanKeyword, KindConstructorKeyword, KindDeclareKeyword, KindGetKeyword, KindImmediateKeyword, KindInferKeyword, KindIntrinsicKeyword, KindIsKeyword, KindKeyOfKeyword, KindModuleKeyword, KindNamespaceKeyword, KindNeverKeyword, KindNotKeyword, KindOutKeyword, KindReadonlyKeyword, KindRequireKeyword, KindNumberKeyword, KindObjectKeyword, KindSatisfiesKeyword, KindSetKeyword, KindStringKeyword, KindSymbolKeyword, KindTypeKeyword, KindUndefinedKeyword, KindUniqueKeyword, KindUnknownKeyword, KindUsingKeyword, KindFromKeyword, KindGlobalKeyword, KindBigIntKeyword, KindOverrideKeyword, KindOfKeyword, KindDeferKeyword: return true } return false diff --git a/tsc/internal/ast/kind_generated.go b/tsc/internal/ast/kind_generated.go index 8c67e7947572f..5d82338431b51 100644 --- a/tsc/internal/ast/kind_generated.go +++ b/tsc/internal/ast/kind_generated.go @@ -164,6 +164,7 @@ const ( KindModuleKeyword KindNamespaceKeyword KindNeverKeyword + KindNotKeyword KindOutKeyword KindReadonlyKeyword KindRequireKeyword @@ -430,11 +431,11 @@ type ( LiteralSyntaxKind = Kind // KindNumericLiteral | KindBigIntLiteral | KindStringLiteral | KindJsxText | KindJsxTextAllWhiteSpaces | KindRegularExpressionLiteral | KindNoSubstitutionTemplateLiteral PseudoLiteralSyntaxKind = Kind // KindTemplateHead | KindTemplateMiddle | KindTemplateTail PunctuationSyntaxKind = Kind // KindOpenBraceToken | KindCloseBraceToken | KindOpenParenToken | KindCloseParenToken | KindOpenBracketToken | KindCloseBracketToken | KindDotToken | KindDotDotDotToken | KindSemicolonToken | KindCommaToken | KindQuestionDotToken | KindLessThanToken | KindLessThanSlashToken | KindGreaterThanToken | KindLessThanEqualsToken | KindGreaterThanEqualsToken | KindEqualsEqualsToken | KindExclamationEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindEqualsGreaterThanToken | KindPlusToken | KindMinusToken | KindAsteriskToken | KindAsteriskAsteriskToken | KindSlashToken | KindPercentToken | KindPlusPlusToken | KindMinusMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindExclamationToken | KindTildeToken | KindAmpersandAmpersandToken | KindBarBarToken | KindQuestionToken | KindColonToken | KindAtToken | KindQuestionQuestionToken | KindBacktickToken | KindHashToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskEqualsToken | KindAsteriskAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken | KindCaretEqualsToken - KeywordSyntaxKind = Kind // KindBreakKeyword | KindCaseKeyword | KindCatchKeyword | KindClassKeyword | KindConstKeyword | KindContinueKeyword | KindDebuggerKeyword | KindDefaultKeyword | KindDeleteKeyword | KindDoKeyword | KindElseKeyword | KindEnumKeyword | KindExportKeyword | KindExtendsKeyword | KindFalseKeyword | KindFinallyKeyword | KindForKeyword | KindFunctionKeyword | KindIfKeyword | KindImportKeyword | KindInKeyword | KindInstanceOfKeyword | KindNewKeyword | KindNullKeyword | KindReturnKeyword | KindSuperKeyword | KindSwitchKeyword | KindThisKeyword | KindThrowKeyword | KindTrueKeyword | KindTryKeyword | KindTypeOfKeyword | KindVarKeyword | KindVoidKeyword | KindWhileKeyword | KindWithKeyword | KindImplementsKeyword | KindInterfaceKeyword | KindLetKeyword | KindPackageKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindStaticKeyword | KindYieldKeyword | KindAbstractKeyword | KindAccessorKeyword | KindAsKeyword | KindAssertsKeyword | KindAssertKeyword | KindAnyKeyword | KindAsyncKeyword | KindAwaitKeyword | KindBooleanKeyword | KindConstructorKeyword | KindDeclareKeyword | KindGetKeyword | KindImmediateKeyword | KindInferKeyword | KindIntrinsicKeyword | KindIsKeyword | KindKeyOfKeyword | KindModuleKeyword | KindNamespaceKeyword | KindNeverKeyword | KindOutKeyword | KindReadonlyKeyword | KindRequireKeyword | KindNumberKeyword | KindObjectKeyword | KindSatisfiesKeyword | KindSetKeyword | KindStringKeyword | KindSymbolKeyword | KindTypeKeyword | KindUndefinedKeyword | KindUniqueKeyword | KindUnknownKeyword | KindUsingKeyword | KindFromKeyword | KindGlobalKeyword | KindBigIntKeyword | KindOverrideKeyword | KindOfKeyword | KindDeferKeyword + KeywordSyntaxKind = Kind // KindBreakKeyword | KindCaseKeyword | KindCatchKeyword | KindClassKeyword | KindConstKeyword | KindContinueKeyword | KindDebuggerKeyword | KindDefaultKeyword | KindDeleteKeyword | KindDoKeyword | KindElseKeyword | KindEnumKeyword | KindExportKeyword | KindExtendsKeyword | KindFalseKeyword | KindFinallyKeyword | KindForKeyword | KindFunctionKeyword | KindIfKeyword | KindImportKeyword | KindInKeyword | KindInstanceOfKeyword | KindNewKeyword | KindNullKeyword | KindReturnKeyword | KindSuperKeyword | KindSwitchKeyword | KindThisKeyword | KindThrowKeyword | KindTrueKeyword | KindTryKeyword | KindTypeOfKeyword | KindVarKeyword | KindVoidKeyword | KindWhileKeyword | KindWithKeyword | KindImplementsKeyword | KindInterfaceKeyword | KindLetKeyword | KindPackageKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindStaticKeyword | KindYieldKeyword | KindAbstractKeyword | KindAccessorKeyword | KindAsKeyword | KindAssertsKeyword | KindAssertKeyword | KindAnyKeyword | KindAsyncKeyword | KindAwaitKeyword | KindBooleanKeyword | KindConstructorKeyword | KindDeclareKeyword | KindGetKeyword | KindImmediateKeyword | KindInferKeyword | KindIntrinsicKeyword | KindIsKeyword | KindKeyOfKeyword | KindModuleKeyword | KindNamespaceKeyword | KindNeverKeyword | KindNotKeyword | KindOutKeyword | KindReadonlyKeyword | KindRequireKeyword | KindNumberKeyword | KindObjectKeyword | KindSatisfiesKeyword | KindSetKeyword | KindStringKeyword | KindSymbolKeyword | KindTypeKeyword | KindUndefinedKeyword | KindUniqueKeyword | KindUnknownKeyword | KindUsingKeyword | KindFromKeyword | KindGlobalKeyword | KindBigIntKeyword | KindOverrideKeyword | KindOfKeyword | KindDeferKeyword ModifierSyntaxKind = Kind // KindAbstractKeyword | KindAccessorKeyword | KindAsyncKeyword | KindConstKeyword | KindDeclareKeyword | KindDefaultKeyword | KindExportKeyword | KindInKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindReadonlyKeyword | KindOutKeyword | KindOverrideKeyword | KindStaticKeyword KeywordTypeSyntaxKind = Kind // KindAnyKeyword | KindBigIntKeyword | KindBooleanKeyword | KindIntrinsicKeyword | KindNeverKeyword | KindNumberKeyword | KindObjectKeyword | KindStringKeyword | KindSymbolKeyword | KindUndefinedKeyword | KindUnknownKeyword | KindVoidKeyword KeywordExpressionSyntaxKind = Kind // KindNullKeyword | KindTrueKeyword | KindFalseKeyword | KindThisKeyword | KindSuperKeyword | KindImportKeyword - TokenSyntaxKind = Kind // KindUnknown | KindEndOfFile | KindSingleLineCommentTrivia | KindMultiLineCommentTrivia | KindNewLineTrivia | KindWhitespaceTrivia | KindConflictMarkerTrivia | KindNonTextFileMarkerTrivia | KindNumericLiteral | KindBigIntLiteral | KindStringLiteral | KindJsxText | KindJsxTextAllWhiteSpaces | KindRegularExpressionLiteral | KindNoSubstitutionTemplateLiteral | KindTemplateHead | KindTemplateMiddle | KindTemplateTail | KindOpenBraceToken | KindCloseBraceToken | KindOpenParenToken | KindCloseParenToken | KindOpenBracketToken | KindCloseBracketToken | KindDotToken | KindDotDotDotToken | KindSemicolonToken | KindCommaToken | KindQuestionDotToken | KindLessThanToken | KindLessThanSlashToken | KindGreaterThanToken | KindLessThanEqualsToken | KindGreaterThanEqualsToken | KindEqualsEqualsToken | KindExclamationEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindEqualsGreaterThanToken | KindPlusToken | KindMinusToken | KindAsteriskToken | KindAsteriskAsteriskToken | KindSlashToken | KindPercentToken | KindPlusPlusToken | KindMinusMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindExclamationToken | KindTildeToken | KindAmpersandAmpersandToken | KindBarBarToken | KindQuestionToken | KindColonToken | KindAtToken | KindQuestionQuestionToken | KindBacktickToken | KindHashToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskEqualsToken | KindAsteriskAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken | KindCaretEqualsToken | KindIdentifier | KindPrivateIdentifier | KindJSDocCommentTextToken | KindBreakKeyword | KindCaseKeyword | KindCatchKeyword | KindClassKeyword | KindConstKeyword | KindContinueKeyword | KindDebuggerKeyword | KindDefaultKeyword | KindDeleteKeyword | KindDoKeyword | KindElseKeyword | KindEnumKeyword | KindExportKeyword | KindExtendsKeyword | KindFalseKeyword | KindFinallyKeyword | KindForKeyword | KindFunctionKeyword | KindIfKeyword | KindImportKeyword | KindInKeyword | KindInstanceOfKeyword | KindNewKeyword | KindNullKeyword | KindReturnKeyword | KindSuperKeyword | KindSwitchKeyword | KindThisKeyword | KindThrowKeyword | KindTrueKeyword | KindTryKeyword | KindTypeOfKeyword | KindVarKeyword | KindVoidKeyword | KindWhileKeyword | KindWithKeyword | KindImplementsKeyword | KindInterfaceKeyword | KindLetKeyword | KindPackageKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindStaticKeyword | KindYieldKeyword | KindAbstractKeyword | KindAccessorKeyword | KindAsKeyword | KindAssertsKeyword | KindAssertKeyword | KindAnyKeyword | KindAsyncKeyword | KindAwaitKeyword | KindBooleanKeyword | KindConstructorKeyword | KindDeclareKeyword | KindGetKeyword | KindImmediateKeyword | KindInferKeyword | KindIntrinsicKeyword | KindIsKeyword | KindKeyOfKeyword | KindModuleKeyword | KindNamespaceKeyword | KindNeverKeyword | KindOutKeyword | KindReadonlyKeyword | KindRequireKeyword | KindNumberKeyword | KindObjectKeyword | KindSatisfiesKeyword | KindSetKeyword | KindStringKeyword | KindSymbolKeyword | KindTypeKeyword | KindUndefinedKeyword | KindUniqueKeyword | KindUnknownKeyword | KindUsingKeyword | KindFromKeyword | KindGlobalKeyword | KindBigIntKeyword | KindOverrideKeyword | KindOfKeyword | KindDeferKeyword + TokenSyntaxKind = Kind // KindUnknown | KindEndOfFile | KindSingleLineCommentTrivia | KindMultiLineCommentTrivia | KindNewLineTrivia | KindWhitespaceTrivia | KindConflictMarkerTrivia | KindNonTextFileMarkerTrivia | KindNumericLiteral | KindBigIntLiteral | KindStringLiteral | KindJsxText | KindJsxTextAllWhiteSpaces | KindRegularExpressionLiteral | KindNoSubstitutionTemplateLiteral | KindTemplateHead | KindTemplateMiddle | KindTemplateTail | KindOpenBraceToken | KindCloseBraceToken | KindOpenParenToken | KindCloseParenToken | KindOpenBracketToken | KindCloseBracketToken | KindDotToken | KindDotDotDotToken | KindSemicolonToken | KindCommaToken | KindQuestionDotToken | KindLessThanToken | KindLessThanSlashToken | KindGreaterThanToken | KindLessThanEqualsToken | KindGreaterThanEqualsToken | KindEqualsEqualsToken | KindExclamationEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindEqualsGreaterThanToken | KindPlusToken | KindMinusToken | KindAsteriskToken | KindAsteriskAsteriskToken | KindSlashToken | KindPercentToken | KindPlusPlusToken | KindMinusMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindExclamationToken | KindTildeToken | KindAmpersandAmpersandToken | KindBarBarToken | KindQuestionToken | KindColonToken | KindAtToken | KindQuestionQuestionToken | KindBacktickToken | KindHashToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskEqualsToken | KindAsteriskAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken | KindCaretEqualsToken | KindIdentifier | KindPrivateIdentifier | KindJSDocCommentTextToken | KindBreakKeyword | KindCaseKeyword | KindCatchKeyword | KindClassKeyword | KindConstKeyword | KindContinueKeyword | KindDebuggerKeyword | KindDefaultKeyword | KindDeleteKeyword | KindDoKeyword | KindElseKeyword | KindEnumKeyword | KindExportKeyword | KindExtendsKeyword | KindFalseKeyword | KindFinallyKeyword | KindForKeyword | KindFunctionKeyword | KindIfKeyword | KindImportKeyword | KindInKeyword | KindInstanceOfKeyword | KindNewKeyword | KindNullKeyword | KindReturnKeyword | KindSuperKeyword | KindSwitchKeyword | KindThisKeyword | KindThrowKeyword | KindTrueKeyword | KindTryKeyword | KindTypeOfKeyword | KindVarKeyword | KindVoidKeyword | KindWhileKeyword | KindWithKeyword | KindImplementsKeyword | KindInterfaceKeyword | KindLetKeyword | KindPackageKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindStaticKeyword | KindYieldKeyword | KindAbstractKeyword | KindAccessorKeyword | KindAsKeyword | KindAssertsKeyword | KindAssertKeyword | KindAnyKeyword | KindAsyncKeyword | KindAwaitKeyword | KindBooleanKeyword | KindConstructorKeyword | KindDeclareKeyword | KindGetKeyword | KindImmediateKeyword | KindInferKeyword | KindIntrinsicKeyword | KindIsKeyword | KindKeyOfKeyword | KindModuleKeyword | KindNamespaceKeyword | KindNeverKeyword | KindNotKeyword | KindOutKeyword | KindReadonlyKeyword | KindRequireKeyword | KindNumberKeyword | KindObjectKeyword | KindSatisfiesKeyword | KindSetKeyword | KindStringKeyword | KindSymbolKeyword | KindTypeKeyword | KindUndefinedKeyword | KindUniqueKeyword | KindUnknownKeyword | KindUsingKeyword | KindFromKeyword | KindGlobalKeyword | KindBigIntKeyword | KindOverrideKeyword | KindOfKeyword | KindDeferKeyword JsxTokenSyntaxKind = Kind // KindLessThanSlashToken | KindEndOfFile | KindConflictMarkerTrivia | KindJsxText | KindJsxTextAllWhiteSpaces | KindOpenBraceToken | KindLessThanToken JSDocNodeSyntaxKind = Kind // KindJSDocTypeExpression | KindJSDocNameReference | KindJSDocAllType | KindJSDocNullableType | KindJSDocNonNullableType | KindJSDocOptionalType | KindJSDocVariadicType | KindJSDoc | KindJSDocText | KindJSDocTypeLiteral | KindJSDocSignature | KindJSDocLink | KindJSDocLinkCode | KindJSDocLinkPlain | KindJSDocUnknownTag | KindJSDocAugmentsTag | KindJSDocImplementsTag | KindJSDocDeprecatedTag | KindJSDocPublicTag | KindJSDocPrivateTag | KindJSDocProtectedTag | KindJSDocReadonlyTag | KindJSDocOverrideTag | KindJSDocCallbackTag | KindJSDocOverloadTag | KindJSDocParameterTag | KindJSDocReturnTag | KindJSDocThisTag | KindJSDocTypeTag | KindJSDocTemplateTag | KindJSDocTypedefTag | KindJSDocSeeTag | KindJSDocPropertyTag | KindJSDocThrowsTag | KindJSDocSatisfiesTag | KindJSDocImportTag ImportPhaseModifierSyntaxKind = Kind // KindTypeKeyword | KindDeferKeyword diff --git a/tsc/internal/ast/kind_stringer_generated.go b/tsc/internal/ast/kind_stringer_generated.go index b80f1ba531982..90fd1ce2500e5 100644 --- a/tsc/internal/ast/kind_stringer_generated.go +++ b/tsc/internal/ast/kind_stringer_generated.go @@ -155,216 +155,217 @@ func _() { _ = x[KindModuleKeyword-144] _ = x[KindNamespaceKeyword-145] _ = x[KindNeverKeyword-146] - _ = x[KindOutKeyword-147] - _ = x[KindReadonlyKeyword-148] - _ = x[KindRequireKeyword-149] - _ = x[KindNumberKeyword-150] - _ = x[KindObjectKeyword-151] - _ = x[KindSatisfiesKeyword-152] - _ = x[KindSetKeyword-153] - _ = x[KindStringKeyword-154] - _ = x[KindSymbolKeyword-155] - _ = x[KindTypeKeyword-156] - _ = x[KindUndefinedKeyword-157] - _ = x[KindUniqueKeyword-158] - _ = x[KindUnknownKeyword-159] - _ = x[KindUsingKeyword-160] - _ = x[KindFromKeyword-161] - _ = x[KindGlobalKeyword-162] - _ = x[KindBigIntKeyword-163] - _ = x[KindOverrideKeyword-164] - _ = x[KindOfKeyword-165] - _ = x[KindDeferKeyword-166] - _ = x[KindQualifiedName-167] - _ = x[KindComputedPropertyName-168] - _ = x[KindTypeParameter-169] - _ = x[KindParameter-170] - _ = x[KindDecorator-171] - _ = x[KindPropertySignature-172] - _ = x[KindPropertyDeclaration-173] - _ = x[KindMethodSignature-174] - _ = x[KindMethodDeclaration-175] - _ = x[KindClassStaticBlockDeclaration-176] - _ = x[KindConstructor-177] - _ = x[KindGetAccessor-178] - _ = x[KindSetAccessor-179] - _ = x[KindCallSignature-180] - _ = x[KindConstructSignature-181] - _ = x[KindIndexSignature-182] - _ = x[KindTypePredicate-183] - _ = x[KindTypeReference-184] - _ = x[KindFunctionType-185] - _ = x[KindConstructorType-186] - _ = x[KindTypeQuery-187] - _ = x[KindTypeLiteral-188] - _ = x[KindArrayType-189] - _ = x[KindTupleType-190] - _ = x[KindOptionalType-191] - _ = x[KindRestType-192] - _ = x[KindUnionType-193] - _ = x[KindIntersectionType-194] - _ = x[KindConditionalType-195] - _ = x[KindInferType-196] - _ = x[KindParenthesizedType-197] - _ = x[KindThisType-198] - _ = x[KindTypeOperator-199] - _ = x[KindIndexedAccessType-200] - _ = x[KindMappedType-201] - _ = x[KindLiteralType-202] - _ = x[KindNamedTupleMember-203] - _ = x[KindTemplateLiteralType-204] - _ = x[KindTemplateLiteralTypeSpan-205] - _ = x[KindImportType-206] - _ = x[KindObjectBindingPattern-207] - _ = x[KindArrayBindingPattern-208] - _ = x[KindBindingElement-209] - _ = x[KindArrayLiteralExpression-210] - _ = x[KindObjectLiteralExpression-211] - _ = x[KindPropertyAccessExpression-212] - _ = x[KindElementAccessExpression-213] - _ = x[KindCallExpression-214] - _ = x[KindNewExpression-215] - _ = x[KindTaggedTemplateExpression-216] - _ = x[KindTypeAssertionExpression-217] - _ = x[KindParenthesizedExpression-218] - _ = x[KindFunctionExpression-219] - _ = x[KindArrowFunction-220] - _ = x[KindDeleteExpression-221] - _ = x[KindTypeOfExpression-222] - _ = x[KindVoidExpression-223] - _ = x[KindAwaitExpression-224] - _ = x[KindPrefixUnaryExpression-225] - _ = x[KindPostfixUnaryExpression-226] - _ = x[KindBinaryExpression-227] - _ = x[KindConditionalExpression-228] - _ = x[KindTemplateExpression-229] - _ = x[KindYieldExpression-230] - _ = x[KindSpreadElement-231] - _ = x[KindClassExpression-232] - _ = x[KindOmittedExpression-233] - _ = x[KindExpressionWithTypeArguments-234] - _ = x[KindAsExpression-235] - _ = x[KindNonNullExpression-236] - _ = x[KindMetaProperty-237] - _ = x[KindSyntheticExpression-238] - _ = x[KindSatisfiesExpression-239] - _ = x[KindTemplateSpan-240] - _ = x[KindSemicolonClassElement-241] - _ = x[KindBlock-242] - _ = x[KindEmptyStatement-243] - _ = x[KindVariableStatement-244] - _ = x[KindExpressionStatement-245] - _ = x[KindIfStatement-246] - _ = x[KindDoStatement-247] - _ = x[KindWhileStatement-248] - _ = x[KindForStatement-249] - _ = x[KindForInStatement-250] - _ = x[KindForOfStatement-251] - _ = x[KindContinueStatement-252] - _ = x[KindBreakStatement-253] - _ = x[KindReturnStatement-254] - _ = x[KindWithStatement-255] - _ = x[KindSwitchStatement-256] - _ = x[KindLabeledStatement-257] - _ = x[KindThrowStatement-258] - _ = x[KindTryStatement-259] - _ = x[KindDebuggerStatement-260] - _ = x[KindVariableDeclaration-261] - _ = x[KindVariableDeclarationList-262] - _ = x[KindFunctionDeclaration-263] - _ = x[KindClassDeclaration-264] - _ = x[KindInterfaceDeclaration-265] - _ = x[KindTypeAliasDeclaration-266] - _ = x[KindEnumDeclaration-267] - _ = x[KindModuleDeclaration-268] - _ = x[KindModuleBlock-269] - _ = x[KindCaseBlock-270] - _ = x[KindNamespaceExportDeclaration-271] - _ = x[KindImportEqualsDeclaration-272] - _ = x[KindImportDeclaration-273] - _ = x[KindImportClause-274] - _ = x[KindNamespaceImport-275] - _ = x[KindNamedImports-276] - _ = x[KindImportSpecifier-277] - _ = x[KindExportAssignment-278] - _ = x[KindExportDeclaration-279] - _ = x[KindNamedExports-280] - _ = x[KindNamespaceExport-281] - _ = x[KindExportSpecifier-282] - _ = x[KindMissingDeclaration-283] - _ = x[KindExternalModuleReference-284] - _ = x[KindJsxElement-285] - _ = x[KindJsxSelfClosingElement-286] - _ = x[KindJsxOpeningElement-287] - _ = x[KindJsxClosingElement-288] - _ = x[KindJsxFragment-289] - _ = x[KindJsxOpeningFragment-290] - _ = x[KindJsxClosingFragment-291] - _ = x[KindJsxAttribute-292] - _ = x[KindJsxAttributes-293] - _ = x[KindJsxSpreadAttribute-294] - _ = x[KindJsxExpression-295] - _ = x[KindJsxNamespacedName-296] - _ = x[KindCaseClause-297] - _ = x[KindDefaultClause-298] - _ = x[KindHeritageClause-299] - _ = x[KindCatchClause-300] - _ = x[KindImportAttributes-301] - _ = x[KindImportAttribute-302] - _ = x[KindPropertyAssignment-303] - _ = x[KindShorthandPropertyAssignment-304] - _ = x[KindSpreadAssignment-305] - _ = x[KindEnumMember-306] - _ = x[KindSourceFile-307] - _ = x[KindJSDocTypeExpression-308] - _ = x[KindJSDocNameReference-309] - _ = x[KindJSDocAllType-310] - _ = x[KindJSDocNullableType-311] - _ = x[KindJSDocNonNullableType-312] - _ = x[KindJSDocOptionalType-313] - _ = x[KindJSDocVariadicType-314] - _ = x[KindJSDoc-315] - _ = x[KindJSDocText-316] - _ = x[KindJSDocTypeLiteral-317] - _ = x[KindJSDocSignature-318] - _ = x[KindJSDocLink-319] - _ = x[KindJSDocLinkCode-320] - _ = x[KindJSDocLinkPlain-321] - _ = x[KindJSDocUnknownTag-322] - _ = x[KindJSDocAugmentsTag-323] - _ = x[KindJSDocImplementsTag-324] - _ = x[KindJSDocDeprecatedTag-325] - _ = x[KindJSDocPublicTag-326] - _ = x[KindJSDocPrivateTag-327] - _ = x[KindJSDocProtectedTag-328] - _ = x[KindJSDocReadonlyTag-329] - _ = x[KindJSDocOverrideTag-330] - _ = x[KindJSDocCallbackTag-331] - _ = x[KindJSDocOverloadTag-332] - _ = x[KindJSDocParameterTag-333] - _ = x[KindJSDocReturnTag-334] - _ = x[KindJSDocThisTag-335] - _ = x[KindJSDocTypeTag-336] - _ = x[KindJSDocTemplateTag-337] - _ = x[KindJSDocTypedefTag-338] - _ = x[KindJSDocSeeTag-339] - _ = x[KindJSDocPropertyTag-340] - _ = x[KindJSDocThrowsTag-341] - _ = x[KindJSDocSatisfiesTag-342] - _ = x[KindJSDocImportTag-343] - _ = x[KindSyntaxList-344] - _ = x[KindJSTypeAliasDeclaration-345] - _ = x[KindJSImportDeclaration-346] - _ = x[KindNotEmittedStatement-347] - _ = x[KindPartiallyEmittedExpression-348] - _ = x[KindSyntheticReferenceExpression-349] - _ = x[KindNotEmittedTypeElement-350] - _ = x[KindCount-351] + _ = x[KindNotKeyword-147] + _ = x[KindOutKeyword-148] + _ = x[KindReadonlyKeyword-149] + _ = x[KindRequireKeyword-150] + _ = x[KindNumberKeyword-151] + _ = x[KindObjectKeyword-152] + _ = x[KindSatisfiesKeyword-153] + _ = x[KindSetKeyword-154] + _ = x[KindStringKeyword-155] + _ = x[KindSymbolKeyword-156] + _ = x[KindTypeKeyword-157] + _ = x[KindUndefinedKeyword-158] + _ = x[KindUniqueKeyword-159] + _ = x[KindUnknownKeyword-160] + _ = x[KindUsingKeyword-161] + _ = x[KindFromKeyword-162] + _ = x[KindGlobalKeyword-163] + _ = x[KindBigIntKeyword-164] + _ = x[KindOverrideKeyword-165] + _ = x[KindOfKeyword-166] + _ = x[KindDeferKeyword-167] + _ = x[KindQualifiedName-168] + _ = x[KindComputedPropertyName-169] + _ = x[KindTypeParameter-170] + _ = x[KindParameter-171] + _ = x[KindDecorator-172] + _ = x[KindPropertySignature-173] + _ = x[KindPropertyDeclaration-174] + _ = x[KindMethodSignature-175] + _ = x[KindMethodDeclaration-176] + _ = x[KindClassStaticBlockDeclaration-177] + _ = x[KindConstructor-178] + _ = x[KindGetAccessor-179] + _ = x[KindSetAccessor-180] + _ = x[KindCallSignature-181] + _ = x[KindConstructSignature-182] + _ = x[KindIndexSignature-183] + _ = x[KindTypePredicate-184] + _ = x[KindTypeReference-185] + _ = x[KindFunctionType-186] + _ = x[KindConstructorType-187] + _ = x[KindTypeQuery-188] + _ = x[KindTypeLiteral-189] + _ = x[KindArrayType-190] + _ = x[KindTupleType-191] + _ = x[KindOptionalType-192] + _ = x[KindRestType-193] + _ = x[KindUnionType-194] + _ = x[KindIntersectionType-195] + _ = x[KindConditionalType-196] + _ = x[KindInferType-197] + _ = x[KindParenthesizedType-198] + _ = x[KindThisType-199] + _ = x[KindTypeOperator-200] + _ = x[KindIndexedAccessType-201] + _ = x[KindMappedType-202] + _ = x[KindLiteralType-203] + _ = x[KindNamedTupleMember-204] + _ = x[KindTemplateLiteralType-205] + _ = x[KindTemplateLiteralTypeSpan-206] + _ = x[KindImportType-207] + _ = x[KindObjectBindingPattern-208] + _ = x[KindArrayBindingPattern-209] + _ = x[KindBindingElement-210] + _ = x[KindArrayLiteralExpression-211] + _ = x[KindObjectLiteralExpression-212] + _ = x[KindPropertyAccessExpression-213] + _ = x[KindElementAccessExpression-214] + _ = x[KindCallExpression-215] + _ = x[KindNewExpression-216] + _ = x[KindTaggedTemplateExpression-217] + _ = x[KindTypeAssertionExpression-218] + _ = x[KindParenthesizedExpression-219] + _ = x[KindFunctionExpression-220] + _ = x[KindArrowFunction-221] + _ = x[KindDeleteExpression-222] + _ = x[KindTypeOfExpression-223] + _ = x[KindVoidExpression-224] + _ = x[KindAwaitExpression-225] + _ = x[KindPrefixUnaryExpression-226] + _ = x[KindPostfixUnaryExpression-227] + _ = x[KindBinaryExpression-228] + _ = x[KindConditionalExpression-229] + _ = x[KindTemplateExpression-230] + _ = x[KindYieldExpression-231] + _ = x[KindSpreadElement-232] + _ = x[KindClassExpression-233] + _ = x[KindOmittedExpression-234] + _ = x[KindExpressionWithTypeArguments-235] + _ = x[KindAsExpression-236] + _ = x[KindNonNullExpression-237] + _ = x[KindMetaProperty-238] + _ = x[KindSyntheticExpression-239] + _ = x[KindSatisfiesExpression-240] + _ = x[KindTemplateSpan-241] + _ = x[KindSemicolonClassElement-242] + _ = x[KindBlock-243] + _ = x[KindEmptyStatement-244] + _ = x[KindVariableStatement-245] + _ = x[KindExpressionStatement-246] + _ = x[KindIfStatement-247] + _ = x[KindDoStatement-248] + _ = x[KindWhileStatement-249] + _ = x[KindForStatement-250] + _ = x[KindForInStatement-251] + _ = x[KindForOfStatement-252] + _ = x[KindContinueStatement-253] + _ = x[KindBreakStatement-254] + _ = x[KindReturnStatement-255] + _ = x[KindWithStatement-256] + _ = x[KindSwitchStatement-257] + _ = x[KindLabeledStatement-258] + _ = x[KindThrowStatement-259] + _ = x[KindTryStatement-260] + _ = x[KindDebuggerStatement-261] + _ = x[KindVariableDeclaration-262] + _ = x[KindVariableDeclarationList-263] + _ = x[KindFunctionDeclaration-264] + _ = x[KindClassDeclaration-265] + _ = x[KindInterfaceDeclaration-266] + _ = x[KindTypeAliasDeclaration-267] + _ = x[KindEnumDeclaration-268] + _ = x[KindModuleDeclaration-269] + _ = x[KindModuleBlock-270] + _ = x[KindCaseBlock-271] + _ = x[KindNamespaceExportDeclaration-272] + _ = x[KindImportEqualsDeclaration-273] + _ = x[KindImportDeclaration-274] + _ = x[KindImportClause-275] + _ = x[KindNamespaceImport-276] + _ = x[KindNamedImports-277] + _ = x[KindImportSpecifier-278] + _ = x[KindExportAssignment-279] + _ = x[KindExportDeclaration-280] + _ = x[KindNamedExports-281] + _ = x[KindNamespaceExport-282] + _ = x[KindExportSpecifier-283] + _ = x[KindMissingDeclaration-284] + _ = x[KindExternalModuleReference-285] + _ = x[KindJsxElement-286] + _ = x[KindJsxSelfClosingElement-287] + _ = x[KindJsxOpeningElement-288] + _ = x[KindJsxClosingElement-289] + _ = x[KindJsxFragment-290] + _ = x[KindJsxOpeningFragment-291] + _ = x[KindJsxClosingFragment-292] + _ = x[KindJsxAttribute-293] + _ = x[KindJsxAttributes-294] + _ = x[KindJsxSpreadAttribute-295] + _ = x[KindJsxExpression-296] + _ = x[KindJsxNamespacedName-297] + _ = x[KindCaseClause-298] + _ = x[KindDefaultClause-299] + _ = x[KindHeritageClause-300] + _ = x[KindCatchClause-301] + _ = x[KindImportAttributes-302] + _ = x[KindImportAttribute-303] + _ = x[KindPropertyAssignment-304] + _ = x[KindShorthandPropertyAssignment-305] + _ = x[KindSpreadAssignment-306] + _ = x[KindEnumMember-307] + _ = x[KindSourceFile-308] + _ = x[KindJSDocTypeExpression-309] + _ = x[KindJSDocNameReference-310] + _ = x[KindJSDocAllType-311] + _ = x[KindJSDocNullableType-312] + _ = x[KindJSDocNonNullableType-313] + _ = x[KindJSDocOptionalType-314] + _ = x[KindJSDocVariadicType-315] + _ = x[KindJSDoc-316] + _ = x[KindJSDocText-317] + _ = x[KindJSDocTypeLiteral-318] + _ = x[KindJSDocSignature-319] + _ = x[KindJSDocLink-320] + _ = x[KindJSDocLinkCode-321] + _ = x[KindJSDocLinkPlain-322] + _ = x[KindJSDocUnknownTag-323] + _ = x[KindJSDocAugmentsTag-324] + _ = x[KindJSDocImplementsTag-325] + _ = x[KindJSDocDeprecatedTag-326] + _ = x[KindJSDocPublicTag-327] + _ = x[KindJSDocPrivateTag-328] + _ = x[KindJSDocProtectedTag-329] + _ = x[KindJSDocReadonlyTag-330] + _ = x[KindJSDocOverrideTag-331] + _ = x[KindJSDocCallbackTag-332] + _ = x[KindJSDocOverloadTag-333] + _ = x[KindJSDocParameterTag-334] + _ = x[KindJSDocReturnTag-335] + _ = x[KindJSDocThisTag-336] + _ = x[KindJSDocTypeTag-337] + _ = x[KindJSDocTemplateTag-338] + _ = x[KindJSDocTypedefTag-339] + _ = x[KindJSDocSeeTag-340] + _ = x[KindJSDocPropertyTag-341] + _ = x[KindJSDocThrowsTag-342] + _ = x[KindJSDocSatisfiesTag-343] + _ = x[KindJSDocImportTag-344] + _ = x[KindSyntaxList-345] + _ = x[KindJSTypeAliasDeclaration-346] + _ = x[KindJSImportDeclaration-347] + _ = x[KindNotEmittedStatement-348] + _ = x[KindPartiallyEmittedExpression-349] + _ = x[KindSyntheticReferenceExpression-350] + _ = x[KindNotEmittedTypeElement-351] + _ = x[KindCount-352] } -const _Kind_name = "KindUnknownKindEndOfFileKindSingleLineCommentTriviaKindMultiLineCommentTriviaKindNewLineTriviaKindWhitespaceTriviaKindConflictMarkerTriviaKindNonTextFileMarkerTriviaKindNumericLiteralKindBigIntLiteralKindStringLiteralKindJsxTextKindJsxTextAllWhiteSpacesKindRegularExpressionLiteralKindNoSubstitutionTemplateLiteralKindTemplateHeadKindTemplateMiddleKindTemplateTailKindOpenBraceTokenKindCloseBraceTokenKindOpenParenTokenKindCloseParenTokenKindOpenBracketTokenKindCloseBracketTokenKindDotTokenKindDotDotDotTokenKindSemicolonTokenKindCommaTokenKindQuestionDotTokenKindLessThanTokenKindLessThanSlashTokenKindGreaterThanTokenKindLessThanEqualsTokenKindGreaterThanEqualsTokenKindEqualsEqualsTokenKindExclamationEqualsTokenKindEqualsEqualsEqualsTokenKindExclamationEqualsEqualsTokenKindEqualsGreaterThanTokenKindPlusTokenKindMinusTokenKindAsteriskTokenKindAsteriskAsteriskTokenKindSlashTokenKindPercentTokenKindPlusPlusTokenKindMinusMinusTokenKindLessThanLessThanTokenKindGreaterThanGreaterThanTokenKindGreaterThanGreaterThanGreaterThanTokenKindAmpersandTokenKindBarTokenKindCaretTokenKindExclamationTokenKindTildeTokenKindAmpersandAmpersandTokenKindBarBarTokenKindQuestionTokenKindColonTokenKindAtTokenKindQuestionQuestionTokenKindBacktickTokenKindHashTokenKindEqualsTokenKindPlusEqualsTokenKindMinusEqualsTokenKindAsteriskEqualsTokenKindAsteriskAsteriskEqualsTokenKindSlashEqualsTokenKindPercentEqualsTokenKindLessThanLessThanEqualsTokenKindGreaterThanGreaterThanEqualsTokenKindGreaterThanGreaterThanGreaterThanEqualsTokenKindAmpersandEqualsTokenKindBarEqualsTokenKindBarBarEqualsTokenKindAmpersandAmpersandEqualsTokenKindQuestionQuestionEqualsTokenKindCaretEqualsTokenKindIdentifierKindPrivateIdentifierKindJSDocCommentTextTokenKindBreakKeywordKindCaseKeywordKindCatchKeywordKindClassKeywordKindConstKeywordKindContinueKeywordKindDebuggerKeywordKindDefaultKeywordKindDeleteKeywordKindDoKeywordKindElseKeywordKindEnumKeywordKindExportKeywordKindExtendsKeywordKindFalseKeywordKindFinallyKeywordKindForKeywordKindFunctionKeywordKindIfKeywordKindImportKeywordKindInKeywordKindInstanceOfKeywordKindNewKeywordKindNullKeywordKindReturnKeywordKindSuperKeywordKindSwitchKeywordKindThisKeywordKindThrowKeywordKindTrueKeywordKindTryKeywordKindTypeOfKeywordKindVarKeywordKindVoidKeywordKindWhileKeywordKindWithKeywordKindImplementsKeywordKindInterfaceKeywordKindLetKeywordKindPackageKeywordKindPrivateKeywordKindProtectedKeywordKindPublicKeywordKindStaticKeywordKindYieldKeywordKindAbstractKeywordKindAccessorKeywordKindAsKeywordKindAssertsKeywordKindAssertKeywordKindAnyKeywordKindAsyncKeywordKindAwaitKeywordKindBooleanKeywordKindConstructorKeywordKindDeclareKeywordKindGetKeywordKindImmediateKeywordKindInferKeywordKindIntrinsicKeywordKindIsKeywordKindKeyOfKeywordKindModuleKeywordKindNamespaceKeywordKindNeverKeywordKindOutKeywordKindReadonlyKeywordKindRequireKeywordKindNumberKeywordKindObjectKeywordKindSatisfiesKeywordKindSetKeywordKindStringKeywordKindSymbolKeywordKindTypeKeywordKindUndefinedKeywordKindUniqueKeywordKindUnknownKeywordKindUsingKeywordKindFromKeywordKindGlobalKeywordKindBigIntKeywordKindOverrideKeywordKindOfKeywordKindDeferKeywordKindQualifiedNameKindComputedPropertyNameKindTypeParameterKindParameterKindDecoratorKindPropertySignatureKindPropertyDeclarationKindMethodSignatureKindMethodDeclarationKindClassStaticBlockDeclarationKindConstructorKindGetAccessorKindSetAccessorKindCallSignatureKindConstructSignatureKindIndexSignatureKindTypePredicateKindTypeReferenceKindFunctionTypeKindConstructorTypeKindTypeQueryKindTypeLiteralKindArrayTypeKindTupleTypeKindOptionalTypeKindRestTypeKindUnionTypeKindIntersectionTypeKindConditionalTypeKindInferTypeKindParenthesizedTypeKindThisTypeKindTypeOperatorKindIndexedAccessTypeKindMappedTypeKindLiteralTypeKindNamedTupleMemberKindTemplateLiteralTypeKindTemplateLiteralTypeSpanKindImportTypeKindObjectBindingPatternKindArrayBindingPatternKindBindingElementKindArrayLiteralExpressionKindObjectLiteralExpressionKindPropertyAccessExpressionKindElementAccessExpressionKindCallExpressionKindNewExpressionKindTaggedTemplateExpressionKindTypeAssertionExpressionKindParenthesizedExpressionKindFunctionExpressionKindArrowFunctionKindDeleteExpressionKindTypeOfExpressionKindVoidExpressionKindAwaitExpressionKindPrefixUnaryExpressionKindPostfixUnaryExpressionKindBinaryExpressionKindConditionalExpressionKindTemplateExpressionKindYieldExpressionKindSpreadElementKindClassExpressionKindOmittedExpressionKindExpressionWithTypeArgumentsKindAsExpressionKindNonNullExpressionKindMetaPropertyKindSyntheticExpressionKindSatisfiesExpressionKindTemplateSpanKindSemicolonClassElementKindBlockKindEmptyStatementKindVariableStatementKindExpressionStatementKindIfStatementKindDoStatementKindWhileStatementKindForStatementKindForInStatementKindForOfStatementKindContinueStatementKindBreakStatementKindReturnStatementKindWithStatementKindSwitchStatementKindLabeledStatementKindThrowStatementKindTryStatementKindDebuggerStatementKindVariableDeclarationKindVariableDeclarationListKindFunctionDeclarationKindClassDeclarationKindInterfaceDeclarationKindTypeAliasDeclarationKindEnumDeclarationKindModuleDeclarationKindModuleBlockKindCaseBlockKindNamespaceExportDeclarationKindImportEqualsDeclarationKindImportDeclarationKindImportClauseKindNamespaceImportKindNamedImportsKindImportSpecifierKindExportAssignmentKindExportDeclarationKindNamedExportsKindNamespaceExportKindExportSpecifierKindMissingDeclarationKindExternalModuleReferenceKindJsxElementKindJsxSelfClosingElementKindJsxOpeningElementKindJsxClosingElementKindJsxFragmentKindJsxOpeningFragmentKindJsxClosingFragmentKindJsxAttributeKindJsxAttributesKindJsxSpreadAttributeKindJsxExpressionKindJsxNamespacedNameKindCaseClauseKindDefaultClauseKindHeritageClauseKindCatchClauseKindImportAttributesKindImportAttributeKindPropertyAssignmentKindShorthandPropertyAssignmentKindSpreadAssignmentKindEnumMemberKindSourceFileKindJSDocTypeExpressionKindJSDocNameReferenceKindJSDocAllTypeKindJSDocNullableTypeKindJSDocNonNullableTypeKindJSDocOptionalTypeKindJSDocVariadicTypeKindJSDocKindJSDocTextKindJSDocTypeLiteralKindJSDocSignatureKindJSDocLinkKindJSDocLinkCodeKindJSDocLinkPlainKindJSDocUnknownTagKindJSDocAugmentsTagKindJSDocImplementsTagKindJSDocDeprecatedTagKindJSDocPublicTagKindJSDocPrivateTagKindJSDocProtectedTagKindJSDocReadonlyTagKindJSDocOverrideTagKindJSDocCallbackTagKindJSDocOverloadTagKindJSDocParameterTagKindJSDocReturnTagKindJSDocThisTagKindJSDocTypeTagKindJSDocTemplateTagKindJSDocTypedefTagKindJSDocSeeTagKindJSDocPropertyTagKindJSDocThrowsTagKindJSDocSatisfiesTagKindJSDocImportTagKindSyntaxListKindJSTypeAliasDeclarationKindJSImportDeclarationKindNotEmittedStatementKindPartiallyEmittedExpressionKindSyntheticReferenceExpressionKindNotEmittedTypeElementKindCount" +const _Kind_name = "KindUnknownKindEndOfFileKindSingleLineCommentTriviaKindMultiLineCommentTriviaKindNewLineTriviaKindWhitespaceTriviaKindConflictMarkerTriviaKindNonTextFileMarkerTriviaKindNumericLiteralKindBigIntLiteralKindStringLiteralKindJsxTextKindJsxTextAllWhiteSpacesKindRegularExpressionLiteralKindNoSubstitutionTemplateLiteralKindTemplateHeadKindTemplateMiddleKindTemplateTailKindOpenBraceTokenKindCloseBraceTokenKindOpenParenTokenKindCloseParenTokenKindOpenBracketTokenKindCloseBracketTokenKindDotTokenKindDotDotDotTokenKindSemicolonTokenKindCommaTokenKindQuestionDotTokenKindLessThanTokenKindLessThanSlashTokenKindGreaterThanTokenKindLessThanEqualsTokenKindGreaterThanEqualsTokenKindEqualsEqualsTokenKindExclamationEqualsTokenKindEqualsEqualsEqualsTokenKindExclamationEqualsEqualsTokenKindEqualsGreaterThanTokenKindPlusTokenKindMinusTokenKindAsteriskTokenKindAsteriskAsteriskTokenKindSlashTokenKindPercentTokenKindPlusPlusTokenKindMinusMinusTokenKindLessThanLessThanTokenKindGreaterThanGreaterThanTokenKindGreaterThanGreaterThanGreaterThanTokenKindAmpersandTokenKindBarTokenKindCaretTokenKindExclamationTokenKindTildeTokenKindAmpersandAmpersandTokenKindBarBarTokenKindQuestionTokenKindColonTokenKindAtTokenKindQuestionQuestionTokenKindBacktickTokenKindHashTokenKindEqualsTokenKindPlusEqualsTokenKindMinusEqualsTokenKindAsteriskEqualsTokenKindAsteriskAsteriskEqualsTokenKindSlashEqualsTokenKindPercentEqualsTokenKindLessThanLessThanEqualsTokenKindGreaterThanGreaterThanEqualsTokenKindGreaterThanGreaterThanGreaterThanEqualsTokenKindAmpersandEqualsTokenKindBarEqualsTokenKindBarBarEqualsTokenKindAmpersandAmpersandEqualsTokenKindQuestionQuestionEqualsTokenKindCaretEqualsTokenKindIdentifierKindPrivateIdentifierKindJSDocCommentTextTokenKindBreakKeywordKindCaseKeywordKindCatchKeywordKindClassKeywordKindConstKeywordKindContinueKeywordKindDebuggerKeywordKindDefaultKeywordKindDeleteKeywordKindDoKeywordKindElseKeywordKindEnumKeywordKindExportKeywordKindExtendsKeywordKindFalseKeywordKindFinallyKeywordKindForKeywordKindFunctionKeywordKindIfKeywordKindImportKeywordKindInKeywordKindInstanceOfKeywordKindNewKeywordKindNullKeywordKindReturnKeywordKindSuperKeywordKindSwitchKeywordKindThisKeywordKindThrowKeywordKindTrueKeywordKindTryKeywordKindTypeOfKeywordKindVarKeywordKindVoidKeywordKindWhileKeywordKindWithKeywordKindImplementsKeywordKindInterfaceKeywordKindLetKeywordKindPackageKeywordKindPrivateKeywordKindProtectedKeywordKindPublicKeywordKindStaticKeywordKindYieldKeywordKindAbstractKeywordKindAccessorKeywordKindAsKeywordKindAssertsKeywordKindAssertKeywordKindAnyKeywordKindAsyncKeywordKindAwaitKeywordKindBooleanKeywordKindConstructorKeywordKindDeclareKeywordKindGetKeywordKindImmediateKeywordKindInferKeywordKindIntrinsicKeywordKindIsKeywordKindKeyOfKeywordKindModuleKeywordKindNamespaceKeywordKindNeverKeywordKindNotKeywordKindOutKeywordKindReadonlyKeywordKindRequireKeywordKindNumberKeywordKindObjectKeywordKindSatisfiesKeywordKindSetKeywordKindStringKeywordKindSymbolKeywordKindTypeKeywordKindUndefinedKeywordKindUniqueKeywordKindUnknownKeywordKindUsingKeywordKindFromKeywordKindGlobalKeywordKindBigIntKeywordKindOverrideKeywordKindOfKeywordKindDeferKeywordKindQualifiedNameKindComputedPropertyNameKindTypeParameterKindParameterKindDecoratorKindPropertySignatureKindPropertyDeclarationKindMethodSignatureKindMethodDeclarationKindClassStaticBlockDeclarationKindConstructorKindGetAccessorKindSetAccessorKindCallSignatureKindConstructSignatureKindIndexSignatureKindTypePredicateKindTypeReferenceKindFunctionTypeKindConstructorTypeKindTypeQueryKindTypeLiteralKindArrayTypeKindTupleTypeKindOptionalTypeKindRestTypeKindUnionTypeKindIntersectionTypeKindConditionalTypeKindInferTypeKindParenthesizedTypeKindThisTypeKindTypeOperatorKindIndexedAccessTypeKindMappedTypeKindLiteralTypeKindNamedTupleMemberKindTemplateLiteralTypeKindTemplateLiteralTypeSpanKindImportTypeKindObjectBindingPatternKindArrayBindingPatternKindBindingElementKindArrayLiteralExpressionKindObjectLiteralExpressionKindPropertyAccessExpressionKindElementAccessExpressionKindCallExpressionKindNewExpressionKindTaggedTemplateExpressionKindTypeAssertionExpressionKindParenthesizedExpressionKindFunctionExpressionKindArrowFunctionKindDeleteExpressionKindTypeOfExpressionKindVoidExpressionKindAwaitExpressionKindPrefixUnaryExpressionKindPostfixUnaryExpressionKindBinaryExpressionKindConditionalExpressionKindTemplateExpressionKindYieldExpressionKindSpreadElementKindClassExpressionKindOmittedExpressionKindExpressionWithTypeArgumentsKindAsExpressionKindNonNullExpressionKindMetaPropertyKindSyntheticExpressionKindSatisfiesExpressionKindTemplateSpanKindSemicolonClassElementKindBlockKindEmptyStatementKindVariableStatementKindExpressionStatementKindIfStatementKindDoStatementKindWhileStatementKindForStatementKindForInStatementKindForOfStatementKindContinueStatementKindBreakStatementKindReturnStatementKindWithStatementKindSwitchStatementKindLabeledStatementKindThrowStatementKindTryStatementKindDebuggerStatementKindVariableDeclarationKindVariableDeclarationListKindFunctionDeclarationKindClassDeclarationKindInterfaceDeclarationKindTypeAliasDeclarationKindEnumDeclarationKindModuleDeclarationKindModuleBlockKindCaseBlockKindNamespaceExportDeclarationKindImportEqualsDeclarationKindImportDeclarationKindImportClauseKindNamespaceImportKindNamedImportsKindImportSpecifierKindExportAssignmentKindExportDeclarationKindNamedExportsKindNamespaceExportKindExportSpecifierKindMissingDeclarationKindExternalModuleReferenceKindJsxElementKindJsxSelfClosingElementKindJsxOpeningElementKindJsxClosingElementKindJsxFragmentKindJsxOpeningFragmentKindJsxClosingFragmentKindJsxAttributeKindJsxAttributesKindJsxSpreadAttributeKindJsxExpressionKindJsxNamespacedNameKindCaseClauseKindDefaultClauseKindHeritageClauseKindCatchClauseKindImportAttributesKindImportAttributeKindPropertyAssignmentKindShorthandPropertyAssignmentKindSpreadAssignmentKindEnumMemberKindSourceFileKindJSDocTypeExpressionKindJSDocNameReferenceKindJSDocAllTypeKindJSDocNullableTypeKindJSDocNonNullableTypeKindJSDocOptionalTypeKindJSDocVariadicTypeKindJSDocKindJSDocTextKindJSDocTypeLiteralKindJSDocSignatureKindJSDocLinkKindJSDocLinkCodeKindJSDocLinkPlainKindJSDocUnknownTagKindJSDocAugmentsTagKindJSDocImplementsTagKindJSDocDeprecatedTagKindJSDocPublicTagKindJSDocPrivateTagKindJSDocProtectedTagKindJSDocReadonlyTagKindJSDocOverrideTagKindJSDocCallbackTagKindJSDocOverloadTagKindJSDocParameterTagKindJSDocReturnTagKindJSDocThisTagKindJSDocTypeTagKindJSDocTemplateTagKindJSDocTypedefTagKindJSDocSeeTagKindJSDocPropertyTagKindJSDocThrowsTagKindJSDocSatisfiesTagKindJSDocImportTagKindSyntaxListKindJSTypeAliasDeclarationKindJSImportDeclarationKindNotEmittedStatementKindPartiallyEmittedExpressionKindSyntheticReferenceExpressionKindNotEmittedTypeElementKindCount" -var _Kind_index = [...]uint16{0, 11, 24, 51, 77, 94, 114, 138, 165, 183, 200, 217, 228, 253, 281, 314, 330, 348, 364, 382, 401, 419, 438, 458, 479, 491, 509, 527, 541, 561, 578, 600, 620, 643, 669, 690, 716, 743, 775, 801, 814, 828, 845, 870, 884, 900, 917, 936, 961, 992, 1034, 1052, 1064, 1078, 1098, 1112, 1139, 1154, 1171, 1185, 1196, 1221, 1238, 1251, 1266, 1285, 1305, 1328, 1359, 1379, 1401, 1432, 1469, 1517, 1541, 1559, 1580, 1613, 1644, 1664, 1678, 1699, 1724, 1740, 1755, 1771, 1787, 1803, 1822, 1841, 1859, 1876, 1889, 1904, 1919, 1936, 1954, 1970, 1988, 2002, 2021, 2034, 2051, 2064, 2085, 2099, 2114, 2131, 2147, 2164, 2179, 2195, 2210, 2224, 2241, 2255, 2270, 2286, 2301, 2322, 2342, 2356, 2374, 2392, 2412, 2429, 2446, 2462, 2481, 2500, 2513, 2531, 2548, 2562, 2578, 2594, 2612, 2634, 2652, 2666, 2686, 2702, 2722, 2735, 2751, 2768, 2788, 2804, 2818, 2837, 2855, 2872, 2889, 2909, 2923, 2940, 2957, 2972, 2992, 3009, 3027, 3043, 3058, 3075, 3092, 3111, 3124, 3140, 3157, 3181, 3198, 3211, 3224, 3245, 3268, 3287, 3308, 3339, 3354, 3369, 3384, 3401, 3423, 3441, 3458, 3475, 3491, 3510, 3523, 3538, 3551, 3564, 3580, 3592, 3605, 3625, 3644, 3657, 3678, 3690, 3706, 3727, 3741, 3756, 3776, 3799, 3826, 3840, 3864, 3887, 3905, 3931, 3958, 3986, 4013, 4031, 4048, 4076, 4103, 4130, 4152, 4169, 4189, 4209, 4227, 4246, 4271, 4297, 4317, 4342, 4364, 4383, 4400, 4419, 4440, 4471, 4487, 4508, 4524, 4547, 4570, 4586, 4611, 4620, 4638, 4659, 4682, 4697, 4712, 4730, 4746, 4764, 4782, 4803, 4821, 4840, 4857, 4876, 4896, 4914, 4930, 4951, 4974, 5001, 5024, 5044, 5068, 5092, 5111, 5132, 5147, 5160, 5190, 5217, 5238, 5254, 5273, 5289, 5308, 5328, 5349, 5365, 5384, 5403, 5425, 5452, 5466, 5491, 5512, 5533, 5548, 5570, 5592, 5608, 5625, 5647, 5664, 5685, 5699, 5716, 5734, 5749, 5769, 5788, 5810, 5841, 5861, 5875, 5889, 5912, 5934, 5950, 5971, 5995, 6016, 6037, 6046, 6059, 6079, 6097, 6110, 6127, 6145, 6164, 6184, 6206, 6228, 6246, 6265, 6286, 6306, 6326, 6346, 6366, 6387, 6405, 6421, 6437, 6457, 6476, 6491, 6511, 6529, 6550, 6568, 6582, 6608, 6631, 6654, 6684, 6716, 6741, 6750} +var _Kind_index = [...]uint16{0, 11, 24, 51, 77, 94, 114, 138, 165, 183, 200, 217, 228, 253, 281, 314, 330, 348, 364, 382, 401, 419, 438, 458, 479, 491, 509, 527, 541, 561, 578, 600, 620, 643, 669, 690, 716, 743, 775, 801, 814, 828, 845, 870, 884, 900, 917, 936, 961, 992, 1034, 1052, 1064, 1078, 1098, 1112, 1139, 1154, 1171, 1185, 1196, 1221, 1238, 1251, 1266, 1285, 1305, 1328, 1359, 1379, 1401, 1432, 1469, 1517, 1541, 1559, 1580, 1613, 1644, 1664, 1678, 1699, 1724, 1740, 1755, 1771, 1787, 1803, 1822, 1841, 1859, 1876, 1889, 1904, 1919, 1936, 1954, 1970, 1988, 2002, 2021, 2034, 2051, 2064, 2085, 2099, 2114, 2131, 2147, 2164, 2179, 2195, 2210, 2224, 2241, 2255, 2270, 2286, 2301, 2322, 2342, 2356, 2374, 2392, 2412, 2429, 2446, 2462, 2481, 2500, 2513, 2531, 2548, 2562, 2578, 2594, 2612, 2634, 2652, 2666, 2686, 2702, 2722, 2735, 2751, 2768, 2788, 2804, 2818, 2832, 2851, 2869, 2886, 2903, 2923, 2937, 2954, 2971, 2986, 3006, 3023, 3041, 3057, 3072, 3089, 3106, 3125, 3138, 3154, 3171, 3195, 3212, 3225, 3238, 3259, 3282, 3301, 3322, 3353, 3368, 3383, 3398, 3415, 3437, 3455, 3472, 3489, 3505, 3524, 3537, 3552, 3565, 3578, 3594, 3606, 3619, 3639, 3658, 3671, 3692, 3704, 3720, 3741, 3755, 3770, 3790, 3813, 3840, 3854, 3878, 3901, 3919, 3945, 3972, 4000, 4027, 4045, 4062, 4090, 4117, 4144, 4166, 4183, 4203, 4223, 4241, 4260, 4285, 4311, 4331, 4356, 4378, 4397, 4414, 4433, 4454, 4485, 4501, 4522, 4538, 4561, 4584, 4600, 4625, 4634, 4652, 4673, 4696, 4711, 4726, 4744, 4760, 4778, 4796, 4817, 4835, 4854, 4871, 4890, 4910, 4928, 4944, 4965, 4988, 5015, 5038, 5058, 5082, 5106, 5125, 5146, 5161, 5174, 5204, 5231, 5252, 5268, 5287, 5303, 5322, 5342, 5363, 5379, 5398, 5417, 5439, 5466, 5480, 5505, 5526, 5547, 5562, 5584, 5606, 5622, 5639, 5661, 5678, 5699, 5713, 5730, 5748, 5763, 5783, 5802, 5824, 5855, 5875, 5889, 5903, 5926, 5948, 5964, 5985, 6009, 6030, 6051, 6060, 6073, 6093, 6111, 6124, 6141, 6159, 6178, 6198, 6220, 6242, 6260, 6279, 6300, 6320, 6340, 6360, 6380, 6401, 6419, 6435, 6451, 6471, 6490, 6505, 6525, 6543, 6564, 6582, 6596, 6622, 6645, 6668, 6698, 6730, 6755, 6764} func (i Kind) String() string { idx := int(i) - 0 diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 2a4ead5003a89..47c6ebfcb243c 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -425,41 +425,50 @@ const ( TypeFactsFalsy TypeFacts = 1 << 23 TypeFactsIsUndefined TypeFacts = 1 << 24 TypeFactsIsNull TypeFacts = 1 << 25 + // The following facts record whether a type could be a particular *falsy* value. Unlike the Falsy + // fact (which is a single "could be falsy at all" bit), these are per-value so that a negated type + // such as `not ""` can surgically exclude a single falsy possibility. They are AND-combined in + // getIntersectionTypeFacts (a value is in an intersection only if it is in every constituent), which + // lets an intersection of negations exclude every falsy value. + TypeFactsCouldBeEmptyString TypeFacts = 1 << 26 + TypeFactsCouldBeZeroNumber TypeFacts = 1 << 27 + TypeFactsCouldBeZeroBigInt TypeFacts = 1 << 28 + TypeFactsCouldBeFalse TypeFacts = 1 << 29 TypeFactsIsUndefinedOrNull TypeFacts = TypeFactsIsUndefined | TypeFactsIsNull - TypeFactsAll TypeFacts = (1 << 27) - 1 + TypeFactsAll TypeFacts = (1 << 30) - 1 // The following members encode facts about particular kinds of types for use in the getTypeFacts function. // The presence of a particular fact means that the given test is true for some (and possibly all) values // of that kind of type. TypeFactsBaseStringStrictFacts TypeFacts = TypeFactsTypeofEQString | TypeFactsTypeofNENumber | TypeFactsTypeofNEBigInt | TypeFactsTypeofNEBoolean | TypeFactsTypeofNESymbol | TypeFactsTypeofNEObject | TypeFactsTypeofNEFunction | TypeFactsTypeofNEHostObject | TypeFactsNEUndefined | TypeFactsNENull | TypeFactsNEUndefinedOrNull TypeFactsBaseStringFacts TypeFacts = TypeFactsBaseStringStrictFacts | TypeFactsEQUndefined | TypeFactsEQNull | TypeFactsEQUndefinedOrNull | TypeFactsFalsy - TypeFactsStringStrictFacts TypeFacts = TypeFactsBaseStringStrictFacts | TypeFactsTruthy | TypeFactsFalsy - TypeFactsStringFacts TypeFacts = TypeFactsBaseStringFacts | TypeFactsTruthy - TypeFactsEmptyStringStrictFacts TypeFacts = TypeFactsBaseStringStrictFacts | TypeFactsFalsy - TypeFactsEmptyStringFacts TypeFacts = TypeFactsBaseStringFacts + TypeFactsStringStrictFacts TypeFacts = TypeFactsBaseStringStrictFacts | TypeFactsTruthy | TypeFactsFalsy | TypeFactsCouldBeEmptyString + TypeFactsStringFacts TypeFacts = TypeFactsBaseStringFacts | TypeFactsTruthy | TypeFactsCouldBeEmptyString + TypeFactsEmptyStringStrictFacts TypeFacts = TypeFactsBaseStringStrictFacts | TypeFactsFalsy | TypeFactsCouldBeEmptyString + TypeFactsEmptyStringFacts TypeFacts = TypeFactsBaseStringFacts | TypeFactsCouldBeEmptyString TypeFactsNonEmptyStringStrictFacts TypeFacts = TypeFactsBaseStringStrictFacts | TypeFactsTruthy TypeFactsNonEmptyStringFacts TypeFacts = TypeFactsBaseStringFacts | TypeFactsTruthy TypeFactsBaseNumberStrictFacts TypeFacts = TypeFactsTypeofEQNumber | TypeFactsTypeofNEString | TypeFactsTypeofNEBigInt | TypeFactsTypeofNEBoolean | TypeFactsTypeofNESymbol | TypeFactsTypeofNEObject | TypeFactsTypeofNEFunction | TypeFactsTypeofNEHostObject | TypeFactsNEUndefined | TypeFactsNENull | TypeFactsNEUndefinedOrNull TypeFactsBaseNumberFacts TypeFacts = TypeFactsBaseNumberStrictFacts | TypeFactsEQUndefined | TypeFactsEQNull | TypeFactsEQUndefinedOrNull | TypeFactsFalsy - TypeFactsNumberStrictFacts TypeFacts = TypeFactsBaseNumberStrictFacts | TypeFactsTruthy | TypeFactsFalsy - TypeFactsNumberFacts TypeFacts = TypeFactsBaseNumberFacts | TypeFactsTruthy - TypeFactsZeroNumberStrictFacts TypeFacts = TypeFactsBaseNumberStrictFacts | TypeFactsFalsy - TypeFactsZeroNumberFacts TypeFacts = TypeFactsBaseNumberFacts + TypeFactsNumberStrictFacts TypeFacts = TypeFactsBaseNumberStrictFacts | TypeFactsTruthy | TypeFactsFalsy | TypeFactsCouldBeZeroNumber + TypeFactsNumberFacts TypeFacts = TypeFactsBaseNumberFacts | TypeFactsTruthy | TypeFactsCouldBeZeroNumber + TypeFactsZeroNumberStrictFacts TypeFacts = TypeFactsBaseNumberStrictFacts | TypeFactsFalsy | TypeFactsCouldBeZeroNumber + TypeFactsZeroNumberFacts TypeFacts = TypeFactsBaseNumberFacts | TypeFactsCouldBeZeroNumber TypeFactsNonZeroNumberStrictFacts TypeFacts = TypeFactsBaseNumberStrictFacts | TypeFactsTruthy TypeFactsNonZeroNumberFacts TypeFacts = TypeFactsBaseNumberFacts | TypeFactsTruthy TypeFactsBaseBigIntStrictFacts TypeFacts = TypeFactsTypeofEQBigInt | TypeFactsTypeofNEString | TypeFactsTypeofNENumber | TypeFactsTypeofNEBoolean | TypeFactsTypeofNESymbol | TypeFactsTypeofNEObject | TypeFactsTypeofNEFunction | TypeFactsTypeofNEHostObject | TypeFactsNEUndefined | TypeFactsNENull | TypeFactsNEUndefinedOrNull TypeFactsBaseBigIntFacts TypeFacts = TypeFactsBaseBigIntStrictFacts | TypeFactsEQUndefined | TypeFactsEQNull | TypeFactsEQUndefinedOrNull | TypeFactsFalsy - TypeFactsBigIntStrictFacts TypeFacts = TypeFactsBaseBigIntStrictFacts | TypeFactsTruthy | TypeFactsFalsy - TypeFactsBigIntFacts TypeFacts = TypeFactsBaseBigIntFacts | TypeFactsTruthy - TypeFactsZeroBigIntStrictFacts TypeFacts = TypeFactsBaseBigIntStrictFacts | TypeFactsFalsy - TypeFactsZeroBigIntFacts TypeFacts = TypeFactsBaseBigIntFacts + TypeFactsBigIntStrictFacts TypeFacts = TypeFactsBaseBigIntStrictFacts | TypeFactsTruthy | TypeFactsFalsy | TypeFactsCouldBeZeroBigInt + TypeFactsBigIntFacts TypeFacts = TypeFactsBaseBigIntFacts | TypeFactsTruthy | TypeFactsCouldBeZeroBigInt + TypeFactsZeroBigIntStrictFacts TypeFacts = TypeFactsBaseBigIntStrictFacts | TypeFactsFalsy | TypeFactsCouldBeZeroBigInt + TypeFactsZeroBigIntFacts TypeFacts = TypeFactsBaseBigIntFacts | TypeFactsCouldBeZeroBigInt TypeFactsNonZeroBigIntStrictFacts TypeFacts = TypeFactsBaseBigIntStrictFacts | TypeFactsTruthy TypeFactsNonZeroBigIntFacts TypeFacts = TypeFactsBaseBigIntFacts | TypeFactsTruthy TypeFactsBaseBooleanStrictFacts TypeFacts = TypeFactsTypeofEQBoolean | TypeFactsTypeofNEString | TypeFactsTypeofNENumber | TypeFactsTypeofNEBigInt | TypeFactsTypeofNESymbol | TypeFactsTypeofNEObject | TypeFactsTypeofNEFunction | TypeFactsTypeofNEHostObject | TypeFactsNEUndefined | TypeFactsNENull | TypeFactsNEUndefinedOrNull TypeFactsBaseBooleanFacts TypeFacts = TypeFactsBaseBooleanStrictFacts | TypeFactsEQUndefined | TypeFactsEQNull | TypeFactsEQUndefinedOrNull | TypeFactsFalsy - TypeFactsBooleanStrictFacts TypeFacts = TypeFactsBaseBooleanStrictFacts | TypeFactsTruthy | TypeFactsFalsy - TypeFactsBooleanFacts TypeFacts = TypeFactsBaseBooleanFacts | TypeFactsTruthy - TypeFactsFalseStrictFacts TypeFacts = TypeFactsBaseBooleanStrictFacts | TypeFactsFalsy - TypeFactsFalseFacts TypeFacts = TypeFactsBaseBooleanFacts + TypeFactsBooleanStrictFacts TypeFacts = TypeFactsBaseBooleanStrictFacts | TypeFactsTruthy | TypeFactsFalsy | TypeFactsCouldBeFalse + TypeFactsBooleanFacts TypeFacts = TypeFactsBaseBooleanFacts | TypeFactsTruthy | TypeFactsCouldBeFalse + TypeFactsFalseStrictFacts TypeFacts = TypeFactsBaseBooleanStrictFacts | TypeFactsFalsy | TypeFactsCouldBeFalse + TypeFactsFalseFacts TypeFacts = TypeFactsBaseBooleanFacts | TypeFactsCouldBeFalse TypeFactsTrueStrictFacts TypeFacts = TypeFactsBaseBooleanStrictFacts | TypeFactsTruthy TypeFactsTrueFacts TypeFacts = TypeFactsBaseBooleanFacts | TypeFactsTruthy TypeFactsSymbolStrictFacts TypeFacts = TypeFactsTypeofEQSymbol | TypeFactsTypeofNEString | TypeFactsTypeofNENumber | TypeFactsTypeofNEBigInt | TypeFactsTypeofNEBoolean | TypeFactsTypeofNEObject | TypeFactsTypeofNEFunction | TypeFactsTypeofNEHostObject | TypeFactsNEUndefined | TypeFactsNENull | TypeFactsNEUndefinedOrNull | TypeFactsTruthy @@ -475,6 +484,9 @@ const ( TypeFactsEmptyObjectFacts TypeFacts = TypeFactsAll & ^TypeFactsIsUndefinedOrNull TypeFactsUnknownFacts TypeFacts = TypeFactsAll & ^TypeFactsIsUndefinedOrNull TypeFactsAllTypeofNE TypeFacts = TypeFactsTypeofNEString | TypeFactsTypeofNENumber | TypeFactsTypeofNEBigInt | TypeFactsTypeofNEBoolean | TypeFactsTypeofNESymbol | TypeFactsTypeofNEObject | TypeFactsTypeofNEFunction | TypeFactsNEUndefined + // The set of facts that indicate a type could be some falsy value. A type whose intersection facts + // retain none of these can never be falsy, so its Falsy fact is spurious and gets cleared. + TypeFactsAllCouldBeFalsy TypeFacts = TypeFactsCouldBeEmptyString | TypeFactsCouldBeZeroNumber | TypeFactsCouldBeZeroBigInt | TypeFactsCouldBeFalse | TypeFactsEQUndefined | TypeFactsEQNull | TypeFactsEQUndefinedOrNull // Masks TypeFactsOrFactsMask TypeFacts = TypeFactsTypeofEQFunction | TypeFactsTypeofNEObject TypeFactsAndFactsMask TypeFacts = TypeFactsAll & ^TypeFactsOrFactsMask @@ -642,6 +654,7 @@ type Checker struct { discriminatedContextualTypes map[DiscriminatedContextualTypeKey]*Type instantiationExpressionTypes map[InstantiationExpressionKey]*Type substitutionTypes map[SubstitutionTypeKey]*Type + negatedTypes map[TypeId]*Type reverseMappedCache map[ReverseMappedTypeKey]*Type reverseHomomorphicMappedCache map[ReverseMappedTypeKey]*Type iterationTypesCache map[IterationTypesKey]IterationTypes @@ -955,6 +968,7 @@ func NewChecker(program Program, tracer *Tracer) (*Checker, *sync.Mutex) { c.discriminatedContextualTypes = make(map[DiscriminatedContextualTypeKey]*Type) c.instantiationExpressionTypes = make(map[InstantiationExpressionKey]*Type) c.substitutionTypes = make(map[SubstitutionTypeKey]*Type) + c.negatedTypes = make(map[TypeId]*Type) c.reverseMappedCache = make(map[ReverseMappedTypeKey]*Type) c.reverseHomomorphicMappedCache = make(map[ReverseMappedTypeKey]*Type) c.iterationTypesCache = make(map[IterationTypesKey]IterationTypes) @@ -18365,7 +18379,9 @@ func (c *Checker) widenTypeForVariableLikeDeclaration(t *Type, declaration *ast. if t.flags&TypeFlagsUniqueESSymbol != 0 && (ast.IsBindingElement(declaration) || declaration.Type() == nil) && t.symbol != c.getSymbolOfDeclaration(declaration) { t = c.esSymbolType } - return c.getWidenedType(t) + // Drop any fresh negated types introduced by control flow narrowing so a CFA-introduced + // 'not X' does not leak into an inferred variable, parameter, or property declaration. + return c.removeOrRegularizeNegatedTypes(c.getWidenedType(t), true /*removeNegatedTypes*/) } // Rest parameters default to type any[], other parameters default to type any if ast.IsParameterDeclaration(declaration) && declaration.AsParameterDeclaration().DotDotDotToken != nil { @@ -20714,7 +20730,9 @@ func (c *Checker) checkIfExpressionRefinesParameter(fn *ast.Node, expr *ast.Node falseCondition := &ast.FlowNode{Flags: ast.FlowFlagsFalseCondition, Node: expr, Antecedent: antecedent} falseSubtype := c.getReducedType(c.getFlowTypeOfReferenceEx(param.Name(), initType, trueType, fn, falseCondition)) if falseSubtype.flags&TypeFlagsNever != 0 { - return trueType + // Strip any fresh negated types introduced by control flow narrowing so a CFA-introduced + // 'not X' does not leak into the inferred type predicate (and thus into emitted declarations). + return c.removeOrRegularizeNegatedTypes(trueType, true /*removeNegatedTypes*/) } return nil } @@ -22303,7 +22321,8 @@ func (c *Checker) couldContainTypeVariablesWorker(t *Type) bool { if objectFlags&ObjectFlagsCouldContainTypeVariablesComputed != 0 { return objectFlags&ObjectFlagsCouldContainTypeVariables != 0 } - result := t.flags&TypeFlagsInstantiable != 0 || + result := t.flags&(TypeFlagsInstantiable & ^TypeFlagsNegated) != 0 || + t.flags&TypeFlagsNegated != 0 && c.couldContainTypeVariables(t.AsNegatedType().baseType) || t.flags&TypeFlagsObject != 0 && !c.isNonGenericTopLevelType(t) && (objectFlags&ObjectFlagsReference != 0 && (t.AsTypeReference().node != nil || core.Some(c.getTypeArguments(t), c.couldContainTypeVariables)) || objectFlags&ObjectFlagsAnonymous != 0 && t.symbol != nil && t.symbol.Flags&(ast.SymbolFlagsFunction|ast.SymbolFlagsMethod|ast.SymbolFlagsClass|ast.SymbolFlagsTypeLiteral|ast.SymbolFlagsObjectLiteral) != 0 && t.symbol.Declarations != nil || objectFlags&(ObjectFlagsMapped|ObjectFlagsReverseMapped|ObjectFlagsObjectRestType|ObjectFlagsInstantiationExpressionType) != 0) || @@ -22387,6 +22406,8 @@ func (c *Checker) instantiateTypeWorker(t *Type, m *TypeMapper, alias *TypeAlias return c.getStringMappingType(t.symbol, c.instantiateType(t.AsStringMappingType().target, m)) case flags&TypeFlagsConditional != 0: return c.getConditionalTypeInstantiation(t, c.combineTypeMappers(t.AsConditionalType().mapper, m), false /*forConstraint*/, alias) + case flags&TypeFlagsNegated != 0: + return c.getNegatedType(c.instantiateType(t.AsNegatedType().baseType, m)) case flags&TypeFlagsSubstitution != 0: newBaseType := c.instantiateType(t.AsSubstitutionType().baseType, m) if c.isNoInferType(t) { @@ -23086,6 +23107,8 @@ func (c *Checker) getTypeFromTypeOperatorNode(node *ast.Node) *Type { } case ast.KindReadonlyKeyword: links.resolvedType = c.getTypeFromTypeNode(argType) + case ast.KindNotKeyword: + links.resolvedType = c.getNegatedType(c.getTypeFromTypeNode(argType)) default: panic("Unhandled case in getTypeFromTypeOperatorNode") } @@ -25015,6 +25038,12 @@ func (c *Checker) getGenericObjectFlags(t *Type) ObjectFlags { } return t.objectFlags & ObjectFlagsIsGenericType } + if t.flags&TypeFlagsNegated != 0 { + // A negated type 'not T' is generic only if its base type is generic. This unwrapping + // mirrors maybeTypeOfKindUnwrapNegations, ensuring e.g. 'not "a"' is not treated as a + // generic (instantiable) type even though Negated is part of InstantiableNonPrimitive. + return c.getGenericObjectFlags(t.AsNegatedType().baseType) + } if t.flags&TypeFlagsInstantiableNonPrimitive != 0 || c.isGenericMappedType(t) || c.isGenericTupleType(t) { combinedFlags |= ObjectFlagsIsGenericObjectType } @@ -25639,7 +25668,11 @@ func (c *Checker) getWidenedLiteralLikeTypeForContextualType(t *Type, contextual if !c.isLiteralOfContextualType(t, contextualType) { t = c.getWidenedUniqueESSymbolType(c.getWidenedLiteralType(t)) } - return c.getRegularTypeOfLiteralType(t) + // Fresh negated types introduced by control flow narrowing are widened away (dropped) when a + // narrowed value escapes into a location that does not itself want a negation, so that 'not X' + // does not leak into an inferred declaration. When the contextual type does mention a negation + // (e.g. a 'not string' parameter or property), the fresh negation is preserved. + return c.getRegularTypeOfLiteralType(c.removeOrRegularizeNegatedTypes(t, containsFreshNegatedType(t) && !containsNegatedType(contextualType))) } func (c *Checker) isLiteralOfContextualType(candidateType *Type, contextualType *Type) bool { @@ -25788,6 +25821,11 @@ func (c *Checker) getUnionTypeWorker(types []*Type, unionReduction UnionReductio } return c.unknownType } + if includes&TypeFlagsIncludesNegated != 0 && c.checkForSaturatedNegatedType(typeSet) { + // A union that contains a type and its complement (e.g. 'T | not T') covers every value, + // so it reduces to 'unknown' -- the union converse of 'T & not T' reducing to 'never'. + return c.unknownType + } if includes&TypeFlagsUndefined != 0 { // If type set contains both undefinedType and missingType, remove missingType if len(typeSet) >= 2 && typeSet[0] == c.undefinedType && typeSet[1] == c.missingType { @@ -25804,6 +25842,11 @@ func (c *Checker) getUnionTypeWorker(types []*Type, unionReduction UnionReductio if includes&TypeFlagsIncludesConstrainedTypeVariable != 0 { typeSet = c.removeConstrainedTypeVariables(typeSet) } + if includes&TypeFlagsIntersection != 0 { + // Cancel complementary 'Base & C' / 'Base & not C' members produced by the true and + // false branches of a control-flow narrowing when those branches rejoin. + typeSet = c.removeComplementaryFreshNegatedTypes(typeSet) + } if unionReduction == UnionReductionSubtype { typeSet = c.removeSubtypes(typeSet, includes&TypeFlagsObject != 0) if typeSet == nil { @@ -25894,6 +25937,9 @@ func (c *Checker) addTypesToUnion(sourceTypes []*Type) ([]*Type, TypeFlags) { if flags&TypeFlagsInstantiable != 0 { includes |= TypeFlagsIncludesInstantiable } + if flags&TypeFlagsNegated != 0 { + includes |= TypeFlagsIncludesNegated + } if flags&TypeFlagsIntersection != 0 && t.objectFlags&ObjectFlagsIsConstrainedTypeVariable != 0 { includes |= TypeFlagsIncludesConstrainedTypeVariable } @@ -26244,6 +26290,12 @@ func (c *Checker) getIntersectionTypeEx(types []*Type, flags IntersectionFlags, if includes&TypeFlagsIncludesMissingType != 0 { typeSet[slices.Index(typeSet, c.undefinedType)] = c.missingType } + if core.Some(typeSet, isNegatedType) { + if c.checkForUnsatisfiedNegatedType(typeSet) { + return c.neverType + } + typeSet = c.removeNegatedSubtypes(typeSet) + } if len(typeSet) == 0 { return c.unknownType } @@ -26357,6 +26409,10 @@ func isIntersectionType(t *Type) bool { return t.flags&TypeFlagsIntersection != 0 } +func isNegatedType(t *Type) bool { + return t.flags&TypeFlagsNegated != 0 +} + func isPrimitiveUnion(t *Type) bool { return t.objectFlags&ObjectFlagsPrimitiveUnion != 0 } @@ -26633,6 +26689,9 @@ func (c *Checker) isPatternLiteralPlaceholderType(t *Type) bool { } return seenPlaceholder } + if t.flags&TypeFlagsNegated != 0 { + return true // Negated types are always placeholders, since they represent arbitrary domains that may include sets of strings + } return t.flags&(TypeFlagsAny|TypeFlagsString|TypeFlagsNumber|TypeFlagsBigInt) != 0 || c.isPatternLiteralType(t) } @@ -27690,6 +27749,8 @@ func (c *Checker) computeBaseConstraint(t *Type, stack []RecursionId) *Type { constraint := c.getConstraintFromConditionalType(t) c.conditionalConstraintDepth-- return c.getNextBaseConstraint(constraint, stack) + case t.flags&TypeFlagsNegated != 0: + return c.unknownType case t.flags&TypeFlagsSubstitution != 0: return c.getNextBaseConstraint(c.getSubstitutionIntersection(t), stack) case c.isGenericTupleType(t): @@ -31102,7 +31163,64 @@ func (c *Checker) hasTypeFacts(t *Type, mask TypeFacts) bool { return c.getTypeFacts(t, mask) != 0 } +func (c *Checker) getNegatedTypeFactsWorker(t *Type) TypeFacts { + // The facts of `not T` are the facts of "every value other than the values in T". Removing values + // from the universe can only remove facts that are unique to those values; all other facts remain + // possible. We therefore start from the broad `unknown` fact set and subtract only the facts implied + // solely by `t`. Note we do *not* reduce `t` to its base constraint, as a generic is *more specific* + // than the base type, meaning the set of values in the negated set is *larger* (and unknowable). + flags := t.flags + switch { + case flags&TypeFlagsNull != 0: + return TypeFactsUnknownFacts & ^(TypeFactsEQNull | TypeFactsEQUndefinedOrNull) + case flags&TypeFlagsUndefined != 0: + return TypeFactsUnknownFacts & ^(TypeFactsEQUndefined | TypeFactsEQUndefinedOrNull) + case flags&TypeFlagsString != 0: + return TypeFactsUnknownFacts & ^(TypeFactsTypeofEQString | TypeFactsCouldBeEmptyString) + case flags&TypeFlagsNumber != 0: + return TypeFactsUnknownFacts & ^(TypeFactsTypeofEQNumber | TypeFactsCouldBeZeroNumber) + case flags&TypeFlagsBigInt != 0: + return TypeFactsUnknownFacts & ^(TypeFactsTypeofEQBigInt | TypeFactsCouldBeZeroBigInt) + case flags&TypeFlagsBoolean != 0: + return TypeFactsUnknownFacts & ^(TypeFactsTypeofEQBoolean | TypeFactsCouldBeFalse) + case flags&TypeFlagsESSymbolLike != 0: + return TypeFactsUnknownFacts & ^TypeFactsTypeofEQSymbol + case flags&TypeFlagsStringLiteral != 0: + // `not ""` can still be any (non-empty) string, so it keeps all string facts and merely loses the + // ability to be the falsy empty string. Enum members are more specific than their literal value, so + // their negation does not imply the associated fact. + if flags&TypeFlagsEnumLiteral == 0 && getStringLiteralValue(t) == "" { + return TypeFactsUnknownFacts & ^TypeFactsCouldBeEmptyString + } + case flags&TypeFlagsNumberLiteral != 0: + if flags&TypeFlagsEnumLiteral == 0 && getNumberLiteralValue(t) == 0 { + return TypeFactsUnknownFacts & ^TypeFactsCouldBeZeroNumber + } + case flags&TypeFlagsBigIntLiteral != 0: + if isZeroBigInt(t) { + return TypeFactsUnknownFacts & ^TypeFactsCouldBeZeroBigInt + } + case flags&TypeFlagsBooleanLiteral != 0: + if t == c.falseType || t == c.regularFalseType { + return TypeFactsUnknownFacts & ^TypeFactsCouldBeFalse + } + } + // For every other type (non-empty string literals, non-zero numeric/bigint literals, `true`, objects, + // symbols, enum members, etc.) removing it from the universe removes no fact, since other values share + // all of its facts. Unions and intersections are hoisted out of the negation during construction. + return TypeFactsUnknownFacts +} + func (c *Checker) getTypeFactsWorker(t *Type, callerOnlyNeeds TypeFacts) TypeFacts { + if t.flags&TypeFlagsNegated != 0 { + return c.getNegatedTypeFactsWorker(t.AsNegatedType().baseType) + } + if t.flags&TypeFlagsIntersection != 0 && core.Some(t.Types(), isNegatedType) { + // An intersection that mentions a negated type must not be reduced to its base constraint below, + // since that discards the negated constituents (whose base constraint is `unknown`). Compute the + // facts from the constituents directly so the negations can refine the result. + return c.getIntersectionTypeFacts(t, callerOnlyNeeds) + } if t.flags&(TypeFlagsIntersection|TypeFlagsInstantiable) != 0 { t = c.getBaseConstraintOfType(t) if t == nil { @@ -31253,7 +31371,16 @@ func (c *Checker) getIntersectionTypeFacts(t *Type, callerOnlyNeeds TypeFacts) T andedFacts &= f } } - return oredFacts&TypeFactsOrFactsMask | andedFacts&TypeFactsAndFactsMask + result := oredFacts&TypeFactsOrFactsMask | andedFacts&TypeFactsAndFactsMask + // The per-falsy-value "could be" facts are AND-combined above (a value is in the intersection only if + // it is in every constituent). If none survive then no value in the intersection is falsy, so a Falsy + // fact that lingered only because each constituent was independently falsy-capable is spurious and gets + // removed. This is what lets `not "" & not 0 & not 0n & not null & not undefined & not false` be seen + // as purely truthy, and `string & not ""` reduce to the non-empty string facts. + if result&TypeFactsFalsy != 0 && result&TypeFactsAllCouldBeFalsy == 0 { + result &^= TypeFactsFalsy + } + return result } func isZeroBigInt(t *Type) bool { diff --git a/tsc/internal/checker/flow.go b/tsc/internal/checker/flow.go index 03b226c9315f0..e1a2597e96ca0 100644 --- a/tsc/internal/checker/flow.go +++ b/tsc/internal/checker/flow.go @@ -481,10 +481,10 @@ func (c *Checker) narrowTypeByBinaryExpression(f *FlowState, t *Type, expr *ast. return c.narrowTypeByTypeof(f, t, right.AsTypeOfExpression(), operator, left, assumeTrue) } if c.isMatchingReference(f.reference, left) { - return c.narrowTypeByEquality(t, operator, right, assumeTrue) + return c.narrowTypeByEquality(t, operator, right, assumeTrue, true /*introduceNegation*/) } if c.isMatchingReference(f.reference, right) { - return c.narrowTypeByEquality(t, operator, left, assumeTrue) + return c.narrowTypeByEquality(t, operator, left, assumeTrue, true /*introduceNegation*/) } if c.strictNullChecks { if c.optionalChainContainsReference(left, f.reference) { @@ -553,7 +553,27 @@ func (c *Checker) narrowTypeByBinaryExpression(f *FlowState, t *Type, expr *ast. return t } -func (c *Checker) narrowTypeByEquality(t *Type, operator ast.Kind, value *ast.Node, assumeTrue bool) *Type { +// Returns true if the type includes the "top" of the type hierarchy, or close enough to it - `unknown`, `{}`, and negated types and intersections thereof +// Used to determine if we should narrow to a literal type in `===` comparisons +func (c *Checker) typeIsTopInclusive(t *Type) bool { + if t.flags&TypeFlagsUnknown != 0 || someType(t, c.IsEmptyAnonymousObjectType) { + return true + } + if t.flags&TypeFlagsNegated != 0 { + return true + } + if t.flags&TypeFlagsIntersection != 0 { + for _, t2 := range t.AsIntersectionType().Types() { + if !c.typeIsTopInclusive(t2) { + return false + } + } + return true + } + return false +} + +func (c *Checker) narrowTypeByEquality(t *Type, operator ast.Kind, value *ast.Node, assumeTrue bool, introduceNegation bool) *Type { if t.flags&TypeFlagsAny != 0 { return t } @@ -578,7 +598,7 @@ func (c *Checker) narrowTypeByEquality(t *Type, operator ast.Kind, value *ast.No return c.getAdjustedTypeWithFacts(t, facts) } if assumeTrue { - if !doubleEquals && (t.flags&TypeFlagsUnknown != 0 || someType(t, c.IsEmptyAnonymousObjectType)) { + if !doubleEquals && c.typeIsTopInclusive(t) { if valueType.flags&(TypeFlagsPrimitive|TypeFlagsNonPrimitive) != 0 || c.IsEmptyAnonymousObjectType(valueType) { return valueType } @@ -604,9 +624,19 @@ func (c *Checker) narrowTypeByEquality(t *Type, operator ast.Kind, value *ast.No return filteredType } } - return c.filterType(t, func(t *Type) bool { + filtered := c.filterType(t, func(t *Type) bool { return !(c.isUnitLikeType(t) && c.areTypesComparable(t, valueType)) }) + // In the false branch of a strict literal comparison, introduce a fresh negation so that a base + // type that overlaps the compared value records the exclusion. For example, the else branch of + // 'n === 0' where 'n: number' produces 'number & not 0'. The negation reduces away for + // constituents already disjoint from the value (e.g. 'string & not 0' -> 'string'). We restrict + // this to strict '==='/'!==' because loose '=='/'!=' coerces operands, so excluding a single + // literal would not soundly capture the comparison's semantics. + if introduceNegation && !doubleEquals { + return c.introduceNegationIntoNarrowedType(filtered, valueType) + } + return filtered } return t } @@ -651,7 +681,32 @@ func (c *Checker) narrowTypeByLiteralExpression(t *Type, literal *ast.LiteralExp if !ok { facts = TypeFactsTypeofNEHostObject } - return c.getAdjustedTypeWithFacts(t, facts) + result := c.getAdjustedTypeWithFacts(t, facts) + if impliedType := c.getImpliedTypeForTypeofNegation(literal.Text()); impliedType != nil { + result = c.introduceNegationIntoNarrowedType(result, impliedType) + } + return result +} + +// getImpliedTypeForTypeofNegation returns the primitive type that a value is known *not* to be in the +// false branch of a 'typeof x === "..."' check, or nil for typeof names whose negation isn't a simple +// primitive. It is used to introduce negated types (e.g. 'not string') during control flow narrowing. +func (c *Checker) getImpliedTypeForTypeofNegation(typeName string) *Type { + switch typeName { + case "string": + return c.stringType + case "number": + return c.numberType + case "bigint": + return c.bigintType + case "boolean": + return c.booleanType + case "symbol": + return c.esSymbolType + case "undefined": + return c.undefinedType + } + return nil } func (c *Checker) narrowTypeByTypeName(t *Type, typeName string) *Type { @@ -718,7 +773,12 @@ func (c *Checker) narrowTypeByDiscriminantProperty(t *Type, access *ast.Node, op } } return c.narrowTypeByDiscriminant(t, access, func(t *Type) *Type { - return c.narrowTypeByEquality(t, operator, value, assumeTrue) + // When narrowing a discriminant property, the narrowed property type is only used for a + // comparability test against each constituent's discriminant. Introducing a negated type here + // would produce a structurally different (though semantically equivalent) negation that + // 'areTypesComparable' may fail to relate to a constituent's existing negated discriminant, so + // we suppress negation introduction on this path. + return c.narrowTypeByEquality(t, operator, value, assumeTrue, false /*introduceNegation*/) }) } @@ -856,12 +916,29 @@ func (c *Checker) getNarrowedType(t *Type, candidate *Type, assumeTrue bool, che return narrowedType } +// introduceNegationIntoNarrowedType intersects each constituent of a control-flow-narrowed type with +// 'not candidate' in the false branch of a narrowing check. The resulting negated intersections are +// reduced away by getIntersectionType when redundant (e.g. 'number & not string' -> 'number'), so this +// only meaningfully affects narrowings whose base type overlaps the removed candidate (such as '{}', +// 'unknown', 'object', or a type parameter). For example, narrowing '{}' in the false branch of +// 'typeof x === "string"' produces '{} & not string'. +func (c *Checker) introduceNegationIntoNarrowedType(t *Type, candidate *Type) *Type { + if t.flags&TypeFlagsNever != 0 || candidate.flags&TypeFlagsNever != 0 { + return t + } + return c.getIntersectionType([]*Type{t, c.getFreshNegatedType(candidate)}) +} + func (c *Checker) getNarrowedTypeWorker(t *Type, candidate *Type, assumeTrue bool, checkDerived bool) *Type { if !assumeTrue { if t == candidate { return c.neverType } if checkDerived { + // 'instanceof' (and other prototype-based) narrowing is nominal, so we deliberately do not + // introduce a structural 'not candidate' here. Many class types lack nominal tags and are + // structural subtypes of one another (e.g. 'Derived2' structurally extends 'Derived1'), so a + // structural negation would unsoundly reduce a nominally-kept constituent to never. return c.filterType(t, func(t *Type) bool { return !c.isTypeDerivedFrom(t, candidate) }) @@ -870,9 +947,9 @@ func (c *Checker) getNarrowedTypeWorker(t *Type, candidate *Type, assumeTrue boo t = c.unknownUnionType } trueType := c.getNarrowedType(t, candidate, true /*assumeTrue*/, false /*checkDerived*/) - return c.recombineUnknownType(c.filterType(t, func(t *Type) bool { + return c.introduceNegationIntoNarrowedType(c.recombineUnknownType(c.filterType(t, func(t *Type) bool { return !c.isTypeSubsetOf(t, trueType) - })) + })), candidate) } if t.flags&TypeFlagsAnyOrUnknown != 0 { return candidate @@ -1170,9 +1247,20 @@ func (c *Checker) narrowTypeBySwitchOnTypeOf(t *Type, data *ast.FlowSwitchClause if hasDefaultClause { // In the default clause we filter constituents down to those that are not-equal to all handled cases. notEqualFacts := c.getNotEqualFactsFromTypeofSwitch(clauseStart, clauseEnd, witnesses) - return c.filterType(t, func(t *Type) bool { + filtered := c.filterType(t, func(t *Type) bool { return c.getTypeFacts(t, notEqualFacts) == notEqualFacts }) + // Mirror the false branch of `if (typeof x === "...")`: introduce a fresh `not ` + // for each handled case whose negation is a simple primitive, so that a base type overlapping + // those primitives (such as `{}` or a type parameter) records the exclusion. + for i, witness := range witnesses { + if (i < clauseStart || i >= clauseEnd) && witness != "" { + if impliedType := c.getImpliedTypeForTypeofNegation(witness); impliedType != nil { + filtered = c.introduceNegationIntoNarrowedType(filtered, impliedType) + } + } + } + return filtered } // In the non-default cause we create a union of the type narrowed by each of the listed cases. clauseWitnesses := witnesses[clauseStart:clauseEnd] diff --git a/tsc/internal/checker/inference.go b/tsc/internal/checker/inference.go index 4bb9d2923d9ab..a49882f2873fa 100644 --- a/tsc/internal/checker/inference.go +++ b/tsc/internal/checker/inference.go @@ -244,6 +244,11 @@ func (c *Checker) inferFromTypes(n *InferenceState, source *Type, target *Type) if source.symbol == target.symbol { c.inferFromTypes(n, source.AsStringMappingType().target, target.AsStringMappingType().target) } + case source.flags&TypeFlagsNegated != 0 && target.flags&TypeFlagsNegated != 0: + // Infer from 'not S' to 'not T' by inferring from the base type S to the base type T. + // Negation reverses subtyping (S <: T implies 'not T' <: 'not S'), so the base types + // occupy a contravariant position and inference is flipped accordingly. + c.inferFromContravariantTypes(n, source.AsNegatedType().baseType, target.AsNegatedType().baseType) case source.flags&TypeFlagsSubstitution != 0: c.inferFromTypes(n, source.AsSubstitutionType().baseType, target) // Make substitute inference at a lower priority diff --git a/tsc/internal/checker/negated.go b/tsc/internal/checker/negated.go new file mode 100644 index 0000000000000..d76612f92a49a --- /dev/null +++ b/tsc/internal/checker/negated.go @@ -0,0 +1,311 @@ +package checker + +import ( + "slices" + + "github.com/microsoft/TypeScript/tsc/internal/core" +) + +// newNegatedType creates a new negated type 'not baseType'. +func (c *Checker) newNegatedType(baseType *Type, flags ObjectFlags) *Type { + data := &NegatedType{} + data.baseType = baseType + return c.newType(TypeFlagsNegated, flags, data) +} + +// getNegatedType constructs the type 'not T', applying the negation identities: +// +// not any => any +// not unknown => never +// not never => unknown +// not not T => T +// not (A | B) => not A & not B (De Morgan) +// +// All other types are wrapped in a (cached) NegatedType. +func (c *Checker) getNegatedType(t *Type) *Type { + switch { + case t.flags&TypeFlagsAny != 0: + return t + case t.flags&TypeFlagsUnknown != 0: + return c.neverType + case t.flags&TypeFlagsNever != 0: + return c.unknownType + case t.flags&TypeFlagsNegated != 0: + return t.AsNegatedType().baseType + case t.flags&TypeFlagsUnion != 0: + return c.getIntersectionType(core.Map(t.Types(), c.getNegatedType)) + } + if cached := c.negatedTypes[t.id]; cached != nil { + return cached + } + result := c.newNegatedType(t, ObjectFlagsNone) + result.AsNegatedType().regularType = result + result.AsNegatedType().freshType = c.newNegatedType(t, ObjectFlagsFreshNegated) + result.AsNegatedType().freshType.AsNegatedType().regularType = result + result.AsNegatedType().freshType.AsNegatedType().freshType = result.AsNegatedType().freshType + c.negatedTypes[t.id] = result + return result +} + +// getFreshNegatedType is like getNegatedType, but the leaf negated types it constructs are marked +// fresh (ObjectFlagsFreshNegated). Fresh negated types are those introduced by control flow +// narrowing (as opposed to written explicitly by the user); they are widened away by getWidenedType +// when a narrowed type escapes into an inferred declaration, so they never leak into emitted +// declaration files. +func (c *Checker) getFreshNegatedType(t *Type) *Type { + negated := c.getNegatedType(t) + if negated.flags&TypeFlagsNegated == 0 { + return negated + } + return negated.AsNegatedType().freshType +} + +// isFreshNegatedType reports whether t is a fresh negated type introduced by control flow narrowing. +func isFreshNegatedType(t *Type) bool { + return t.flags&TypeFlagsNegated != 0 && t.objectFlags&ObjectFlagsFreshNegated != 0 +} + +// containsFreshNegatedType reports whether t is a fresh negated type or (transitively) contains one +// within a union or intersection. ObjectFlagsFreshNegated is a TypeFlagsNegated-only flag (its bit +// is reused for other meanings on unions and intersections), so it must never be read directly on a +// container type; this helper recurses instead. +func containsFreshNegatedType(t *Type) bool { + if isFreshNegatedType(t) { + return true + } + if t.flags&TypeFlagsUnionOrIntersection != 0 { + return core.Some(t.Types(), containsFreshNegatedType) + } + return false +} + +// containsNegatedType reports whether t is a negated type or (transitively) contains one within a +// union or intersection. It is used to decide whether a location wants a negation (and should +// therefore preserve a fresh control-flow negation rather than widening it away). +func containsNegatedType(t *Type) bool { + if t == nil { + return false + } + if t.flags&TypeFlagsNegated != 0 { + return true + } + if t.flags&TypeFlagsUnionOrIntersection != 0 { + return core.Some(t.Types(), containsNegatedType) + } + return false +} + +// removeFreshNegatedTypes strips fresh negated types (introduced by control flow narrowing) from t. +// It is used at inference barriers that do not go through getWidenedType (such as inferred type +// predicates) so that a CFA-introduced 'not X' never leaks into an inferred declaration. +func (c *Checker) removeFreshNegatedTypes(t *Type) *Type { + if !containsFreshNegatedType(t) { + return t + } + return c.removeFreshNegatedTypesEx(t, false) +} + +func (c *Checker) removeFreshNegatedTypesEx(t *Type, intersectionMember bool) *Type { + return c.mapType(t, func(t *Type) *Type { + if isFreshNegatedType(t) { + if intersectionMember { + return c.unknownType + } + return c.neverType + } + if t.flags&TypeFlagsIntersection != 0 { + return c.getIntersectionType(core.Map(t.Types(), func(t *Type) *Type { + return c.removeFreshNegatedTypesEx(t, true) + })) + } + return t + }) +} + +func (c *Checker) getRegularNegatedTypes(t *Type) *Type { + if !containsFreshNegatedType(t) { + return t + } + return c.mapType(t, func(t *Type) *Type { + if t.flags&TypeFlagsNegated != 0 { + return t.AsNegatedType().regularType + } + if t.flags&TypeFlagsIntersection != 0 { + return c.getIntersectionType(core.Map(t.Types(), c.getRegularNegatedTypes)) + } + return t + }) +} + +func (c *Checker) removeOrRegularizeNegatedTypes(t *Type, remove bool) *Type { + if remove { + return c.removeFreshNegatedTypes(t) + } + return c.getRegularNegatedTypes(t) +} + +// removeComplementaryFreshNegatedTypes cancels complementary members of a union that were produced +// by the true and false branches of a control-flow narrowing. When both a refined type 'Base & C' +// and its negated complement 'Base & not C' appear in the union, they cover all of 'Base', so both +// are replaced by the common supertype 'Base'. For example, when the branches of +// +// if (crate.isPackedTight()) { ... } +// +// rejoin, the union '(Crate & {extraContents}) | (Crate & not (Crate & {extraContents}))' +// simplifies back to just 'Crate'. This is gated on ObjectFlagsFreshNegated so it only affects +// negations introduced by narrowing, not negations written explicitly by the user. +// +// The input slice is assumed to be sorted (per CompareTypes); the result remains sorted. +func (c *Checker) removeComplementaryFreshNegatedTypes(types []*Type) []*Type { + for i := 0; i < len(types); i++ { + n := types[i] + if n.flags&TypeFlagsIntersection == 0 || !core.Some(n.Types(), isFreshNegatedType) { + continue + } + members := n.Types() + for _, m := range members { + if !isFreshNegatedType(m) { + continue + } + // 'base' is 'n' with this one negation removed; 'positive' is 'base' with the negation's + // base type intersected back in (i.e. the corresponding true-branch member). + rest := core.Filter(members, func(other *Type) bool { return other != m }) + if len(rest) == 0 { + continue + } + base := c.getIntersectionType(rest) + positive := c.getIntersectionType([]*Type{base, m.AsNegatedType().baseType}) + // Find the true-branch counterpart P. Narrowing may have reduced it (e.g. 'Crate & + // Crate' to just 'Crate'), so match structurally: any P with + // (base & C) <: P <: base satisfies 'P | (base & not C) == base'. + j := -1 + for k, p := range types { + if k != i && c.isTypeSubtypeOf(p, base) && c.isTypeSubtypeOf(positive, p) { + j = k + break + } + } + if j < 0 { + continue + } + lo, hi := i, j + if lo > hi { + lo, hi = hi, lo + } + types = slices.Delete(types, hi, hi+1) + types = slices.Delete(types, lo, lo+1) + types, _ = insertType(types, base) + i = -1 // Restart the scan since the set changed. + break + } + } + if core.Some(types, isNegatedType) { + // Union type construction does this reduction *before* this intersection one - it may need to be checked again with the updated type set. + if c.checkForSaturatedNegatedType(types) { + return []*Type{c.unknownType} + } + } + return types +} + +// checkForUnsatisfiedNegatedType returns true if the intersection in typeSet is empty (never) +// because some non-negated member is a subtype of the union of the negated members' base types. +// For example, in '"w" & not string' the non-negated member '"w"' is a subtype of 'string' +// (the base type of 'not string'), so the intersection reduces to never. +func (c *Checker) checkForUnsatisfiedNegatedType(typeSet []*Type) bool { + nonNegatedSet := core.Filter(typeSet, func(t *Type) bool { return t.flags&TypeFlagsNegated == 0 }) + if len(nonNegatedSet) == 0 { + return false + } + negatedBounds := c.getUnionType(core.Map(core.Filter(typeSet, isNegatedType), func(t *Type) *Type { + return t.AsNegatedType().baseType + })) + for _, nonNegatedType := range nonNegatedSet { + if c.isTypeSubtypeOf(nonNegatedType, negatedBounds) { + return true + } + } + return false +} + +// checkForSaturatedNegatedType returns true if the union in typeSet covers every value (i.e. is the +// unknown type) because it contains a type and its complement. This is the union converse of +// checkForUnsatisfiedNegatedType: when a negated member 'not B' is combined with non-negated members +// whose union is a supertype of 'B', the non-negated part covers 'B' and 'not B' covers everything +// else, so the union is unknown. For example, 'T | not T' reduces to unknown, and 'string | not "w"' +// reduces to unknown because '"w"' is a subtype of 'string'. +func (c *Checker) checkForSaturatedNegatedType(typeSet []*Type) bool { + nonNegatedSet := core.Filter(typeSet, func(t *Type) bool { return t.flags&TypeFlagsNegated == 0 }) + if len(nonNegatedSet) == 0 { + return false + } + nonNegatedUnion := c.getUnionType(nonNegatedSet) + for _, negatedType := range core.Filter(typeSet, isNegatedType) { + if c.isTypeSubtypeOf(negatedType.AsNegatedType().baseType, nonNegatedUnion) { + return true + } + } + return false +} + +// removeNegatedSubtypes removes redundant negated members from an intersection. A member 'not X' +// is redundant when the combined non-negated part of the intersection is already a subtype of +// 'not X' (i.e. it is disjoint from X). For example, in 'false & not true' the non-negated part +// 'false' is a subtype of 'not true', so 'not true' is dropped, leaving just 'false'. +// +// A member 'not X' is also redundant when the non-negated part is mutually exclusive with X by +// virtue of a shared discriminant property (see isDisjointByDiscriminant). For example, given +// discriminated types 'A = { kind: "a" }' and 'C = { kind: "c" }', the intersection 'C & not A' +// reduces to 'C' because no value of type C can be an A. +func (c *Checker) removeNegatedSubtypes(types []*Type) []*Type { + if len(types) == 0 { + return types + } + nonNegatedBounds := core.Filter(types, func(t *Type) bool { return t.flags&TypeFlagsNegated == 0 }) + if len(nonNegatedBounds) == 0 { + return types + } + nonNegativePart := c.getIntersectionType(nonNegatedBounds) + for i := len(types) - 1; i >= 0; i-- { + if types[i].flags&TypeFlagsNegated == 0 { + continue + } + negatedBase := types[i].AsNegatedType().baseType + if c.isTypeSubtypeOf(nonNegativePart, types[i]) || c.isDisjointByDiscriminant(nonNegativePart, negatedBase) { + types = slices.Delete(types, i, i+1) + } + } + return types +} + +// isDisjointByDiscriminant reports whether types 'a' and 'b' are provably mutually exclusive because +// they share a discriminant property whose types in 'a' and 'b' have an empty (never) intersection. +// For example '{ kind: "c" }' and '{ kind: "a" }' are disjoint by their 'kind' property, so +// 'C & not A' reduces to 'C'. +// +// Discriminant properties are located with findDiscriminantProperties over the union 'a | b' -- the +// same mechanism used for discriminated-union narrowing -- and disjointness of a single discriminant +// is decided by intersecting the two property types and checking for never. Deciding disjointness by +// intersecting the property types (rather than comparing them by identity) is important: an enum +// literal such as 'E.A' (where 'enum E { A = "a" }') is a distinct type from the string literal '"a"' +// yet is not mutually exclusive with it, so 'E.A & "a"' is not never. +// +// Only the (small, literal) discriminant property types are intersected here, never the full input +// types, so this stays cheap and avoids the circularities a general 'a & b is never' computation +// would risk during intersection construction. +func (c *Checker) isDisjointByDiscriminant(a *Type, b *Type) bool { + union := c.getUnionType([]*Type{a, b}) + if union.flags&TypeFlagsUnion == 0 { + // 'a' and 'b' collapsed into a single type (e.g. one is a subtype of the other), so there is + // no discriminant to distinguish them. + return false + } + for _, prop := range c.findDiscriminantProperties(c.getPropertiesOfType(a), union) { + aPropType := c.getTypeOfPropertyOfType(a, prop.Name) + bPropType := c.getTypeOfPropertyOfType(b, prop.Name) + if aPropType != nil && bPropType != nil && c.getIntersectionType([]*Type{aPropType, bPropType}).flags&TypeFlagsNever != 0 { + return true + } + } + return false +} diff --git a/tsc/internal/checker/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index 53007b500e8c6..e2d108609fbef 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -3524,6 +3524,11 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { if t.flags&TypeFlagsConditional != 0 { return b.visitAndTransformType(t, (*NodeBuilderImpl).conditionalTypeToTypeNode) } + if t.flags&TypeFlagsNegated != 0 { + b.ctx.approximateLength += 4 + baseTypeNode := b.typeToTypeNode(t.AsNegatedType().baseType) + return b.f.NewTypeOperatorNode(ast.KindNotKeyword, baseTypeNode) + } if t.flags&TypeFlagsSubstitution != 0 { typeNode := b.typeToTypeNode(t.AsSubstitutionType().baseType) if !b.ch.isNoInferType(t) { diff --git a/tsc/internal/checker/relater.go b/tsc/internal/checker/relater.go index 9008420fb7cd1..4978214c73e55 100644 --- a/tsc/internal/checker/relater.go +++ b/tsc/internal/checker/relater.go @@ -1083,7 +1083,8 @@ func (c *Checker) isDiscriminantProperty(t *Type, name string) bool { if prop != nil && prop.CheckFlags&ast.CheckFlagsSyntheticProperty != 0 { if prop.CheckFlags&ast.CheckFlagsIsDiscriminantComputed == 0 { prop.CheckFlags |= ast.CheckFlagsIsDiscriminantComputed - if prop.CheckFlags&ast.CheckFlagsNonUniformAndLiteral == ast.CheckFlagsNonUniformAndLiteral && !c.isGenericType(c.getTypeOfSymbol(prop)) { + pt := c.getTypeOfSymbol(prop) + if prop.CheckFlags&ast.CheckFlagsNonUniformAndLiteral == ast.CheckFlagsNonUniformAndLiteral && !c.isGenericType(pt) { prop.CheckFlags |= ast.CheckFlagsIsDiscriminant } } @@ -2316,7 +2317,7 @@ func (c *Checker) getEffectiveConstraintOfIntersection(types []*Type, targetIsUn var constraints []*Type hasDisjointDomainType := false for _, t := range types { - if t.flags&TypeFlagsInstantiable != 0 { + if t.flags&TypeFlagsInstantiable != 0 && t.flags&TypeFlagsNegated == 0 { // We keep following constraints as long as we have an instantiable type that is known // not to be circular or infinite (hence we stop on index access types). constraint := c.getConstraintOfType(t) @@ -2329,7 +2330,7 @@ func (c *Checker) getEffectiveConstraintOfIntersection(types []*Type, targetIsUn constraints = append(constraints, t) } } - } else if t.flags&TypeFlagsDisjointDomains != 0 || c.IsEmptyAnonymousObjectType(t) { + } else if t.flags&(TypeFlagsDisjointDomains|TypeFlagsNegated) != 0 || c.IsEmptyAnonymousObjectType(t) { hasDisjointDomainType = true } } @@ -2340,7 +2341,7 @@ func (c *Checker) getEffectiveConstraintOfIntersection(types []*Type, targetIsUn // We add any types belong to one of the disjoint domains because they might cause the final // intersection operation to reduce the union constraints. for _, t := range types { - if t.flags&TypeFlagsDisjointDomains != 0 || c.IsEmptyAnonymousObjectType(t) { + if t.flags&(TypeFlagsDisjointDomains|TypeFlagsNegated) != 0 || c.IsEmptyAnonymousObjectType(t) { constraints = append(constraints, t) } } @@ -2918,7 +2919,7 @@ func (r *Relater) unionOrIntersectionRelatedTo(source *Type, target *Type, repor // appear to be comparable to '2'. if r.relation == r.c.comparableRelation && target.flags&TypeFlagsPrimitive != 0 { constraints := core.SameMap(source.Types(), func(t *Type) *Type { - if t.flags&TypeFlagsInstantiable != 0 { + if t.flags&(TypeFlagsInstantiable & ^TypeFlagsNegated) != 0 { constraint := r.c.getBaseConstraintOfType(t) if constraint != nil { return constraint @@ -2945,7 +2946,25 @@ func (r *Relater) unionOrIntersectionRelatedTo(source *Type, target *Type, repor // Don't report errors though. Elaborating on whether a source constituent is related to the target is // not actually useful and leads to some confusing error messages. Instead, we rely on the caller // checking whether the full intersection viewed as an object is related to the target. - return r.someTypeRelatedToType(source, target, false /*reportErrors*/, IntersectionStateSource) + result := r.someTypeRelatedToType(source, target, false /*reportErrors*/, IntersectionStateSource) + if r.relation == r.c.comparableRelation { + // In the comparable relation we may have, e.g., 'string & not "a"' being related to '"a"' because + // 'string' and '"a"' are usually comparable - it's only the additional domain limiting provided by + // the negated intersection that narrows further. So we collect the negated domain bits and check + // that the target is comparable with each. If there's any negated domain bit for which it's not + // comparable, then the intersection as a whole shouldn't be comparable. + for _, negation := range source.Types() { + if negation.flags&TypeFlagsNegated == 0 { + continue + } + rel := r.isRelatedTo(target, negation, RecursionFlagsTarget, false /*reportErrors*/) + result &= rel + if result == TernaryFalse { + break + } + } + } + return result } func (r *Relater) someTypeRelatedToType(source *Type, target *Type, reportErrors bool, intersectionState IntersectionState) Ternary { @@ -3397,6 +3416,9 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo if source.AsStringMappingType().Symbol() == target.AsStringMappingType().Symbol() { return r.isRelatedTo(source.AsStringMappingType().target, target.AsStringMappingType().target, RecursionFlagsBoth, false /*reportErrors*/) } + case source.flags&TypeFlagsNegated != 0: + // 'not S' is identical to 'not T' if S is identical to T. + return r.isRelatedTo(source.AsNegatedType().baseType, target.AsNegatedType().baseType, RecursionFlagsBoth, false /*reportErrors*/) } if source.flags&TypeFlagsObject == 0 { return TernaryFalse @@ -3452,6 +3474,41 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo } } switch { + case target.flags&TypeFlagsNegated != 0: + if source.flags&TypeFlagsNegated != 0 { + // 'not S' is related to 'not T' if T is related to S. + return r.isRelatedTo(target.AsNegatedType().baseType, source.AsNegatedType().baseType, RecursionFlagsBoth, reportErrors) + } + // A type S is related to 'not T' if S and T are disjoint, i.e. S & T is never. + if r.c.getIntersectionType([]*Type{source, target.AsNegatedType().baseType}).flags&TypeFlagsNever != 0 { + return TernaryTrue + } + // A fresh object literal type is treated as a closed set of values that have exactly the + // declared properties. Such a type is disjoint from T (and thus related to 'not T') precisely + // when it is not related to T, since excess property checking prevents its values from + // acquiring the extra properties that T might otherwise require. We compare the regular + // (non-fresh) form so that the excess property check itself doesn't interfere with the + // structural comparison. + if isObjectLiteralType(source) { + switch r.isRelatedTo(r.c.getRegularTypeOfObjectLiteral(source), target.AsNegatedType().baseType, RecursionFlagsBoth, false /*reportErrors*/) { + case TernaryFalse: + // The closed object literal is disjoint from T, so it is related to 'not T'. + return TernaryTrue + case TernaryMaybe: + // The comparison was assumed related under recursion; propagate the assumption. + return TernaryMaybe + default: + // The object literal is (possibly) a member of T, so it is not related to 'not T'. + return TernaryFalse + } + } + // Otherwise, if the source is a concrete (non-instantiable) type, it overlaps with T and is therefore + // not related to 'not T'. We must not fall through to the generic instantiable handling below, which + // would relate S to the (permissive) constraint of the negated type and incorrectly report relatedness. + // For instantiable sources we do fall through, so that constraint-based reasoning can still apply. + if source.flags&TypeFlagsInstantiable == 0 { + return TernaryFalse + } case target.flags&TypeFlagsTypeParameter != 0: // A source type { [P in Q]: X } is related to a target type T if keyof T is related to Q and X is related to T[Q]. if source.objectFlags&ObjectFlagsMapped != 0 && source.AsMappedType().declaration.NameType == nil && r.isRelatedTo(r.c.getIndexType(target), r.c.getConstraintTypeFromMappedType(source), RecursionFlagsBoth, false) != TernaryFalse { @@ -3694,6 +3751,17 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo } } switch { + case source.flags&TypeFlagsNegated != 0: + // 'not S' is related to a non-negated type T only via its base constraint (unknown), + // i.e. essentially only when T is 'unknown' or 'any'. + constraint := r.c.getBaseConstraintOfType(source) + if constraint == nil { + constraint = r.c.unknownType + } + result = r.isRelatedTo(constraint, target, RecursionFlagsSource, reportErrors) + if result != TernaryFalse { + return result + } case source.flags&TypeFlagsTypeVariable != 0: // IndexedAccess comparisons are handled above in the `target.flags&TypeFlagsIndexedAccess` branch if source.flags&TypeFlagsIndexedAccess == 0 || target.flags&TypeFlagsIndexedAccess == 0 { @@ -4770,12 +4838,13 @@ func (r *Relater) reportErrorResults(originalSource *Type, originalTarget *Type, } } r.reportRelationError(headMessage, source, target) - if source.flags&TypeFlagsTypeParameter != 0 && source.symbol != nil && len(source.symbol.Declarations) != 0 && r.c.getConstraintOfType(source) == nil { - syntheticParam := r.c.cloneTypeParameter(source) - syntheticParam.AsTypeParameter().constraint = r.c.instantiateType(target, newSimpleTypeMapper(source, syntheticParam)) + filteredSource := r.c.removeFreshNegatedTypes(source) // strip fresh negated types from the source for the next related info span + if filteredSource.flags&TypeFlagsTypeParameter != 0 && filteredSource.symbol != nil && len(filteredSource.symbol.Declarations) != 0 && r.c.getConstraintOfType(filteredSource) == nil { + syntheticParam := r.c.cloneTypeParameter(filteredSource) + syntheticParam.AsTypeParameter().constraint = r.c.instantiateType(target, newSimpleTypeMapper(filteredSource, syntheticParam)) if r.c.hasNonCircularBaseConstraint(syntheticParam) { targetConstraintString := r.c.TypeToString(target) - r.relatedInfo = append(r.relatedInfo, NewDiagnosticForNode(source.symbol.Declarations[0], diagnostics.This_type_parameter_might_need_an_extends_0_constraint, targetConstraintString)) + r.relatedInfo = append(r.relatedInfo, NewDiagnosticForNode(filteredSource.symbol.Declarations[0], diagnostics.This_type_parameter_might_need_an_extends_0_constraint, targetConstraintString)) } } } diff --git a/tsc/internal/checker/types.go b/tsc/internal/checker/types.go index 144124e63c598..84c622ac542ee 100644 --- a/tsc/internal/checker/types.go +++ b/tsc/internal/checker/types.go @@ -423,7 +423,7 @@ type SignatureLinks struct { decoratorSignature *Signature // Signature for decorator as if invoked by the runtime } -type TypeFlags uint32 +type TypeFlags uint64 // Note that for types of different kinds, the numeric values of TypeFlags determine the order // computed by the CompareTypes function and therefore the order of constituent types in union types. @@ -458,13 +458,14 @@ const ( TypeFlagsTemplateLiteral TypeFlags = 1 << 22 // Template literal type TypeFlagsStringMapping TypeFlags = 1 << 23 // Uppercase/Lowercase type TypeFlagsSubstitution TypeFlags = 1 << 24 // Type parameter substitution - TypeFlagsIndexedAccess TypeFlags = 1 << 25 // T[K] - TypeFlagsConditional TypeFlags = 1 << 26 // T extends U ? X : Y - TypeFlagsUnion TypeFlags = 1 << 27 // Union (T | U) - TypeFlagsIntersection TypeFlags = 1 << 28 // Intersection (T & U) - TypeFlagsReserved1 TypeFlags = 1 << 29 // Used by union/intersection type construction - TypeFlagsReserved2 TypeFlags = 1 << 30 // Used by union/intersection type construction - TypeFlagsReserved3 TypeFlags = 1 << 31 + TypeFlagsNegated TypeFlags = 1 << 25 // not T + TypeFlagsIndexedAccess TypeFlags = 1 << 26 // T[K] + TypeFlagsConditional TypeFlags = 1 << 27 // T extends U ? X : Y + TypeFlagsUnion TypeFlags = 1 << 28 // Union (T | U) + TypeFlagsIntersection TypeFlags = 1 << 29 // Intersection (T & U) + TypeFlagsReserved1 TypeFlags = 1 << 30 // Used by union/intersection type construction + TypeFlagsReserved2 TypeFlags = 1 << 31 // Used by union/intersection type construction + TypeFlagsReserved3 TypeFlags = 1 << 32 TypeFlagsAnyOrUnknown = TypeFlagsAny | TypeFlagsUnknown TypeFlagsNullable = TypeFlagsUndefined | TypeFlagsNull @@ -489,7 +490,7 @@ const ( TypeFlagsUnionOrIntersection = TypeFlagsUnion | TypeFlagsIntersection TypeFlagsStructuredType = TypeFlagsObject | TypeFlagsUnion | TypeFlagsIntersection TypeFlagsTypeVariable = TypeFlagsTypeParameter | TypeFlagsIndexedAccess - TypeFlagsInstantiableNonPrimitive = TypeFlagsTypeVariable | TypeFlagsConditional | TypeFlagsSubstitution + TypeFlagsInstantiableNonPrimitive = TypeFlagsTypeVariable | TypeFlagsConditional | TypeFlagsSubstitution | TypeFlagsNegated TypeFlagsInstantiablePrimitive = TypeFlagsIndex | TypeFlagsTemplateLiteral | TypeFlagsStringMapping TypeFlagsInstantiable = TypeFlagsInstantiableNonPrimitive | TypeFlagsInstantiablePrimitive TypeFlagsStructuredOrInstantiable = TypeFlagsStructuredType | TypeFlagsInstantiable @@ -509,6 +510,7 @@ const ( TypeFlagsIncludesInstantiable = TypeFlagsSubstitution TypeFlagsIncludesConstrainedTypeVariable = TypeFlagsReserved1 TypeFlagsIncludesError = TypeFlagsReserved2 + TypeFlagsIncludesNegated = TypeFlagsReserved3 TypeFlagsNotPrimitiveUnion = TypeFlagsAny | TypeFlagsUnknown | TypeFlagsVoid | TypeFlagsNever | TypeFlagsObject | TypeFlagsIntersection | TypeFlagsIncludesInstantiable ) @@ -545,11 +547,12 @@ var typeFlagNames = [...]struct { {TypeFlagsConditional, "Conditional"}, {TypeFlagsUnion, "Union"}, {TypeFlagsIntersection, "Intersection"}, + {TypeFlagsNegated, "Negated"}, } // FormatTypeFlags returns the individual flag names as a slice of strings. func FormatTypeFlags(flags TypeFlags) []string { - result := make([]string, 0, bits.OnesCount32(uint32(flags))) + result := make([]string, 0, bits.OnesCount64(uint64(flags))) for _, fn := range typeFlagNames { if flags&fn.flag != 0 { result = append(result, fn.name) @@ -653,6 +656,8 @@ const ( ObjectFlagsIsNeverIntersectionComputed = 1 << 25 // IsNeverLike flag has been computed ObjectFlagsIsNeverIntersection = 1 << 26 // Intersection reduces to never ObjectFlagsIsConstrainedTypeVariable = 1 << 27 // T & C, where T's constraint and C are primitives, object, or {} + // Flags that require TypeFlags.Negated + ObjectFlagsFreshNegated ObjectFlags = 1 << 25 // Negated type introduced by control flow narrowing; widened away when it escapes into an inferred declaration ) // TypeAlias @@ -721,6 +726,7 @@ func (t *Type) AsTemplateLiteralType() *TemplateLiteralType { return t.data.(*Te func (t *Type) AsStringMappingType() *StringMappingType { return t.data.(*StringMappingType) } func (t *Type) AsSubstitutionType() *SubstitutionType { return t.data.(*SubstitutionType) } func (t *Type) AsConditionalType() *ConditionalType { return t.data.(*ConditionalType) } +func (t *Type) AsNegatedType() *NegatedType { return t.data.(*NegatedType) } // Casts for embedded struct types @@ -1234,6 +1240,17 @@ type SubstitutionType struct { func (t *SubstitutionType) BaseType() *Type { return t.baseType } func (t *SubstitutionType) SubstConstraint() *Type { return t.constraint } +// NegatedType (the type 'not T') + +type NegatedType struct { + ConstrainedType + baseType *Type // The negated type T in 'not T' + freshType *Type // Fresh version of type + regularType *Type // Regular version of type +} + +func (t *NegatedType) BaseType() *Type { return t.baseType } + type ConditionalRoot struct { node *ast.ConditionalTypeNode checkType *Type diff --git a/tsc/internal/parser/parser.go b/tsc/internal/parser/parser.go index 8b53a39b0cda3..cb3cbed2a2777 100644 --- a/tsc/internal/parser/parser.go +++ b/tsc/internal/parser/parser.go @@ -2721,7 +2721,7 @@ func (p *Parser) createUnionOrIntersectionTypeNode(operator ast.Kind, types *ast func (p *Parser) parseTypeOperatorOrHigher() *ast.TypeNode { operator := p.token switch operator { - case ast.KindKeyOfKeyword, ast.KindUniqueKeyword, ast.KindReadonlyKeyword: + case ast.KindKeyOfKeyword, ast.KindUniqueKeyword, ast.KindReadonlyKeyword, ast.KindNotKeyword: return p.parseTypeOperator(operator) case ast.KindInferKeyword: return p.parseInferType() diff --git a/tsc/internal/scanner/scanner.go b/tsc/internal/scanner/scanner.go index 6958b4ab09246..0b713a3670e2f 100644 --- a/tsc/internal/scanner/scanner.go +++ b/tsc/internal/scanner/scanner.go @@ -81,6 +81,7 @@ var textToKeyword = map[string]ast.Kind{ "namespace": ast.KindNamespaceKeyword, "never": ast.KindNeverKeyword, "new": ast.KindNewKeyword, + "not": ast.KindNotKeyword, "null": ast.KindNullKeyword, "number": ast.KindNumberKeyword, "object": ast.KindObjectKeyword, diff --git a/tsc/testdata/baselines/reference/compiler/arrayDestructuringInSwitch1.errors.txt b/tsc/testdata/baselines/reference/compiler/arrayDestructuringInSwitch1.errors.txt new file mode 100644 index 0000000000000..d5b0152c9a956 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/arrayDestructuringInSwitch1.errors.txt @@ -0,0 +1,27 @@ +arrayDestructuringInSwitch1.ts(19,12): error TS2367: This comparison appears to be unintentional because the types '("false" | "true") & not any[]' and 'string' have no overlap. + + +==== arrayDestructuringInSwitch1.ts (1 errors) ==== + export type Expression = BooleanLogicExpression | 'true' | 'false'; + export type BooleanLogicExpression = ['and', ...Expression[]] | ['not', Expression]; + + export function evaluate(expression: Expression): boolean { + if (Array.isArray(expression)) { + const [operator, ...operands] = expression; + switch (operator) { + case 'and': { + return operands.every((child) => evaluate(child)); + } + case 'not': { + return !evaluate(operands[0]); + } + default: { + throw new Error(`${operator} is not a supported operator`); + } + } + } else { + return expression === 'true'; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2367: This comparison appears to be unintentional because the types '("false" | "true") & not any[]' and 'string' have no overlap. + } + } \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/arrayDestructuringInSwitch1.types b/tsc/testdata/baselines/reference/compiler/arrayDestructuringInSwitch1.types index 52cd25f0bd0f4..62eb205a9fbf1 100644 --- a/tsc/testdata/baselines/reference/compiler/arrayDestructuringInSwitch1.types +++ b/tsc/testdata/baselines/reference/compiler/arrayDestructuringInSwitch1.types @@ -62,7 +62,7 @@ export function evaluate(expression: Expression): boolean { } else { return expression === 'true'; >expression === 'true' : boolean ->expression : "false" | "true" +>expression : ("false" | "true") & not any[] >'true' : "true" } } diff --git a/tsc/testdata/baselines/reference/compiler/coAndContraVariantInferences2.types b/tsc/testdata/baselines/reference/compiler/coAndContraVariantInferences2.types index c6b21b22b0e5f..c0d78da6b5af8 100644 --- a/tsc/testdata/baselines/reference/compiler/coAndContraVariantInferences2.types +++ b/tsc/testdata/baselines/reference/compiler/coAndContraVariantInferences2.types @@ -106,7 +106,7 @@ function f3(arr: readonly B[] | readonly C[]) { } else { arr; // readonly B[] ->arr : readonly B[] +>arr : readonly B[] & not readonly C[] } } diff --git a/tsc/testdata/baselines/reference/compiler/constructorWithCapturedSuper.types b/tsc/testdata/baselines/reference/compiler/constructorWithCapturedSuper.types index b34db673f1f2b..57fd217c56b0d 100644 --- a/tsc/testdata/baselines/reference/compiler/constructorWithCapturedSuper.types +++ b/tsc/testdata/baselines/reference/compiler/constructorWithCapturedSuper.types @@ -33,7 +33,7 @@ class B extends A { } while (x < 2) { >x < 2 : boolean ->x : number +>x : number & not 1 >2 : 2 return; diff --git a/tsc/testdata/baselines/reference/compiler/continueInLoopsWithCapturedBlockScopedBindings1(target=es2015).types b/tsc/testdata/baselines/reference/compiler/continueInLoopsWithCapturedBlockScopedBindings1(target=es2015).types index 447d2903bbc2c..1a460f1e9dd76 100644 --- a/tsc/testdata/baselines/reference/compiler/continueInLoopsWithCapturedBlockScopedBindings1(target=es2015).types +++ b/tsc/testdata/baselines/reference/compiler/continueInLoopsWithCapturedBlockScopedBindings1(target=es2015).types @@ -20,12 +20,12 @@ function foo() { // Trigger non-simple-loop emit (() => { ->(() => { return i; })() : number ->(() => { return i; }) : () => number ->() => { return i; } : () => number +>(() => { return i; })() : number & not 0 +>(() => { return i; }) : () => number & not 0 +>() => { return i; } : () => number & not 0 return i; ->i : number +>i : number & not 0 })(); } diff --git a/tsc/testdata/baselines/reference/compiler/controlFlowDestructuringLoop.types b/tsc/testdata/baselines/reference/compiler/controlFlowDestructuringLoop.types index 3dce96915ee7d..02b9c49f09642 100644 --- a/tsc/testdata/baselines/reference/compiler/controlFlowDestructuringLoop.types +++ b/tsc/testdata/baselines/reference/compiler/controlFlowDestructuringLoop.types @@ -52,7 +52,7 @@ function foo(things: Val[]): void { else { const { val } = thing; >val : string ->thing : StrVal +>thing : StrVal & not NumVal val.length; >val.length : number diff --git a/tsc/testdata/baselines/reference/compiler/controlFlowFavorAssertedTypeThroughTypePredicate.types b/tsc/testdata/baselines/reference/compiler/controlFlowFavorAssertedTypeThroughTypePredicate.types index 5aec7dbee617a..ef827ca10e717 100644 --- a/tsc/testdata/baselines/reference/compiler/controlFlowFavorAssertedTypeThroughTypePredicate.types +++ b/tsc/testdata/baselines/reference/compiler/controlFlowFavorAssertedTypeThroughTypePredicate.types @@ -25,7 +25,7 @@ if (isObject1(obj1)) { } // check type after conditional block obj1; ->obj1 : {} +>obj1 : Record declare const obj2: {} | undefined; >obj2 : {} | undefined @@ -45,7 +45,7 @@ if (isObject1(obj2)) { } // check type after conditional block obj2; ->obj2 : {} | undefined +>obj2 : Record | undefined declare function isObject2(value: unknown): value is {}; >isObject2 : (value: unknown) => value is {} diff --git a/tsc/testdata/baselines/reference/compiler/controlFlowUnionContainingTypeParameter1.types b/tsc/testdata/baselines/reference/compiler/controlFlowUnionContainingTypeParameter1.types index 07a9a8afbaf95..0c9a56f6f6206 100644 --- a/tsc/testdata/baselines/reference/compiler/controlFlowUnionContainingTypeParameter1.types +++ b/tsc/testdata/baselines/reference/compiler/controlFlowUnionContainingTypeParameter1.types @@ -46,7 +46,7 @@ class TestClass { >this.f : (v: number) => void >this : this >f : (v: number) => void ->val : number +>val : number & not T } } @@ -89,14 +89,14 @@ class TestClass2 { return; } val; ->val : number +>val : number & not T this.f(val); >this.f(val) : void >this.f : (v: number) => void >this : this >f : (v: number) => void ->val : number +>val : number & not T } } diff --git a/tsc/testdata/baselines/reference/compiler/declFileTypeAnnotationStringLiteral(target=es2015).types b/tsc/testdata/baselines/reference/compiler/declFileTypeAnnotationStringLiteral(target=es2015).types index f6f1ec56a63c2..47899fe8835ba 100644 --- a/tsc/testdata/baselines/reference/compiler/declFileTypeAnnotationStringLiteral(target=es2015).types +++ b/tsc/testdata/baselines/reference/compiler/declFileTypeAnnotationStringLiteral(target=es2015).types @@ -29,5 +29,5 @@ function foo(a: string): string | number { } return a; ->a : string +>a : string & not "hello" } diff --git a/tsc/testdata/baselines/reference/compiler/discriminantsAndPrimitives.types b/tsc/testdata/baselines/reference/compiler/discriminantsAndPrimitives.types index f60f4342c3867..2f126b1879bca 100644 --- a/tsc/testdata/baselines/reference/compiler/discriminantsAndPrimitives.types +++ b/tsc/testdata/baselines/reference/compiler/discriminantsAndPrimitives.types @@ -31,7 +31,7 @@ function f1(x: Foo | Bar | string) { switch(x.kind) { >x.kind : "bar" | "foo" ->x : Bar | Foo +>x : (Bar | Foo) & not string >kind : "bar" | "foo" case 'foo': @@ -39,7 +39,7 @@ function f1(x: Foo | Bar | string) { x.name; >x.name : string ->x : Foo +>x : Foo & not string >name : string } } @@ -85,7 +85,7 @@ function f3(x: Foo | Bar | string | null) { switch(x.kind) { >x.kind : "bar" | "foo" ->x : Bar | Foo +>x : (Bar | Foo) & not string >kind : "bar" | "foo" case 'foo': @@ -93,7 +93,7 @@ function f3(x: Foo | Bar | string | null) { x.name; >x.name : string ->x : Foo +>x : Foo & not string >name : string } } diff --git a/tsc/testdata/baselines/reference/compiler/distributiveConditionalTypeConstraints.types b/tsc/testdata/baselines/reference/compiler/distributiveConditionalTypeConstraints.types index d38a982f44c8a..0afb018df8afd 100644 --- a/tsc/testdata/baselines/reference/compiler/distributiveConditionalTypeConstraints.types +++ b/tsc/testdata/baselines/reference/compiler/distributiveConditionalTypeConstraints.types @@ -180,7 +180,7 @@ function test3(y: T extends C ? number : string) { } else { y; // T extends C ? number : string ->y : T extends C ? number : string +>y : (T extends C ? number : string) & not string } const newY: string | number = y; >newY : string | number @@ -205,7 +205,7 @@ function test4(y: T extends C ? string : number) { } else { y; // T extends C ? string : number ->y : T extends C ? string : number +>y : (T extends C ? string : number) & not string } const newY: string | number = y; >newY : string | number diff --git a/tsc/testdata/baselines/reference/compiler/doubleUnderscoreLabels.types b/tsc/testdata/baselines/reference/compiler/doubleUnderscoreLabels.types index c631dcbb519d9..0407a5d56be0f 100644 --- a/tsc/testdata/baselines/reference/compiler/doubleUnderscoreLabels.types +++ b/tsc/testdata/baselines/reference/compiler/doubleUnderscoreLabels.types @@ -16,7 +16,7 @@ function doThing() { >i : number >10 : 10 >i++ : number ->i : number +>i : number & not 3 & not 5 if (i === 3) { >i === 3 : boolean @@ -28,7 +28,7 @@ function doThing() { } if (i === 5) { >i === 5 : boolean ->i : number +>i : number & not 3 >5 : 5 break aLabel; diff --git a/tsc/testdata/baselines/reference/compiler/duplicateLocalVariable1.types b/tsc/testdata/baselines/reference/compiler/duplicateLocalVariable1.types index 2e2f6b501634b..659174adc8ccd 100644 --- a/tsc/testdata/baselines/reference/compiler/duplicateLocalVariable1.types +++ b/tsc/testdata/baselines/reference/compiler/duplicateLocalVariable1.types @@ -145,9 +145,9 @@ export class TestRunner { >regex : RegExp >new RegExp(testcase.errorMessageRegEx) : RegExp >RegExp : RegExpConstructor ->testcase.errorMessageRegEx : string +>testcase.errorMessageRegEx : string & not "" >testcase : TestCase ->errorMessageRegEx : string +>errorMessageRegEx : string & not "" testResult = regex.test(e.message); >testResult = regex.test(e.message) : boolean diff --git a/tsc/testdata/baselines/reference/compiler/emptyAnonymousObjectNarrowing(strictnullchecks=false).types b/tsc/testdata/baselines/reference/compiler/emptyAnonymousObjectNarrowing(strictnullchecks=false).types index c9807fa2b6a26..d599401da3e19 100644 --- a/tsc/testdata/baselines/reference/compiler/emptyAnonymousObjectNarrowing(strictnullchecks=false).types +++ b/tsc/testdata/baselines/reference/compiler/emptyAnonymousObjectNarrowing(strictnullchecks=false).types @@ -14,7 +14,7 @@ if (nonNull === "foo") { } else { nonNull; ->nonNull : {} +>nonNull : {} & not "foo" } declare let obj: { a: string }; diff --git a/tsc/testdata/baselines/reference/compiler/emptyAnonymousObjectNarrowing(strictnullchecks=true).types b/tsc/testdata/baselines/reference/compiler/emptyAnonymousObjectNarrowing(strictnullchecks=true).types index 29367e5df7797..18e70362d0e40 100644 --- a/tsc/testdata/baselines/reference/compiler/emptyAnonymousObjectNarrowing(strictnullchecks=true).types +++ b/tsc/testdata/baselines/reference/compiler/emptyAnonymousObjectNarrowing(strictnullchecks=true).types @@ -14,7 +14,7 @@ if (nonNull === "foo") { } else { nonNull; ->nonNull : {} +>nonNull : {} & not "foo" } declare let obj: { a: string }; diff --git a/tsc/testdata/baselines/reference/compiler/emptyThenWithoutWarning.types b/tsc/testdata/baselines/reference/compiler/emptyThenWithoutWarning.types index 714c202ae6b23..07be0c5fec4b6 100644 --- a/tsc/testdata/baselines/reference/compiler/emptyThenWithoutWarning.types +++ b/tsc/testdata/baselines/reference/compiler/emptyThenWithoutWarning.types @@ -12,10 +12,10 @@ if(a === 1 || a === 2 || a === 3) { >a : number >1 : 1 >a === 2 : boolean ->a : number +>a : number & not 1 >2 : 2 >a === 3 : boolean ->a : number +>a : number & not 1 & not 2 >3 : 3 } else { diff --git a/tsc/testdata/baselines/reference/compiler/genericCapturingFunctionNarrowing.types b/tsc/testdata/baselines/reference/compiler/genericCapturingFunctionNarrowing.types index 0778b7c7568c8..64e2585d750ca 100644 --- a/tsc/testdata/baselines/reference/compiler/genericCapturingFunctionNarrowing.types +++ b/tsc/testdata/baselines/reference/compiler/genericCapturingFunctionNarrowing.types @@ -30,7 +30,7 @@ function needsToNarrowTheTypeconsole : Console >log : (...data: any[]) => void >thing.bar : string ->thing : Second +>thing : Second & not First >bar : string } diff --git a/tsc/testdata/baselines/reference/compiler/getterSetterSubtypeAssignment.types b/tsc/testdata/baselines/reference/compiler/getterSetterSubtypeAssignment.types index efbc5c4d6e776..03206c995a581 100644 --- a/tsc/testdata/baselines/reference/compiler/getterSetterSubtypeAssignment.types +++ b/tsc/testdata/baselines/reference/compiler/getterSetterSubtypeAssignment.types @@ -253,9 +253,9 @@ class NumberOrObject { >this : this >_x : number >this._x.bar : number ->this._x : Foo +>this._x : Foo & not number >this : this ->_x : Foo +>_x : Foo & not number >bar : number set x(value: number | Foo) { this._x = value; } diff --git a/tsc/testdata/baselines/reference/compiler/inDoesNotOperateOnPrimitiveTypes.errors.txt b/tsc/testdata/baselines/reference/compiler/inDoesNotOperateOnPrimitiveTypes.errors.txt index f627cfba48352..0ad57d3251d2e 100644 --- a/tsc/testdata/baselines/reference/compiler/inDoesNotOperateOnPrimitiveTypes.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/inDoesNotOperateOnPrimitiveTypes.errors.txt @@ -12,7 +12,7 @@ inDoesNotOperateOnPrimitiveTypes.ts(27,12): error TS2322: Type 'T | U' is not as Type 'string' is not assignable to type 'object'. inDoesNotOperateOnPrimitiveTypes.ts(34,12): error TS2322: Type 'string | number | T' is not assignable to type 'object'. Type 'string' is not assignable to type 'object'. -inDoesNotOperateOnPrimitiveTypes.ts(36,14): error TS2322: Type 'T' is not assignable to type 'object'. +inDoesNotOperateOnPrimitiveTypes.ts(36,14): error TS2322: Type 'T & not string & not number' is not assignable to type 'object'. inDoesNotOperateOnPrimitiveTypes.ts(41,12): error TS2322: Type 'T' is not assignable to type 'object'. Type '"hello" | object' is not assignable to type 'object'. Type 'string' is not assignable to type 'object'. @@ -83,7 +83,7 @@ inDoesNotOperateOnPrimitiveTypes.ts(64,12): error TS2322: Type 'T & (0 | 1 | 2)' if (typeof thing !== "string" && typeof thing !== "number") { "key" in thing; // Ok (because further narrowing is impossible) ~~~~~ -!!! error TS2322: Type 'T' is not assignable to type 'object'. +!!! error TS2322: Type 'T & not string & not number' is not assignable to type 'object'. !!! related TS2208 inDoesNotOperateOnPrimitiveTypes.ts:33:17: This type parameter might need an `extends object` constraint. } } diff --git a/tsc/testdata/baselines/reference/compiler/inDoesNotOperateOnPrimitiveTypes.types b/tsc/testdata/baselines/reference/compiler/inDoesNotOperateOnPrimitiveTypes.types index a5f65767dd8da..6e5c1a4765503 100644 --- a/tsc/testdata/baselines/reference/compiler/inDoesNotOperateOnPrimitiveTypes.types +++ b/tsc/testdata/baselines/reference/compiler/inDoesNotOperateOnPrimitiveTypes.types @@ -102,13 +102,13 @@ function union3(thing: T | string | number) { >"string" : "string" >typeof thing !== "number" : boolean >typeof thing : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->thing : number | T +>thing : number | (T & not string) >"number" : "number" "key" in thing; // Ok (because further narrowing is impossible) >"key" in thing : boolean >"key" : "key" ->thing : T +>thing : T & not string & not number } } diff --git a/tsc/testdata/baselines/reference/compiler/inKeywordTypeguard(strict=false).types b/tsc/testdata/baselines/reference/compiler/inKeywordTypeguard(strict=false).types index dcc5f67852776..48deb265cc313 100644 --- a/tsc/testdata/baselines/reference/compiler/inKeywordTypeguard(strict=false).types +++ b/tsc/testdata/baselines/reference/compiler/inKeywordTypeguard(strict=false).types @@ -1102,14 +1102,14 @@ function test1>(obj: T) { >obj : any[] | Record >'length' in obj : boolean >'length' : "length" ->obj : T +>obj : T & not any[] obj; // T >obj : T } else { obj; // T ->obj : T +>obj : T & not any[] } } @@ -1129,7 +1129,7 @@ function test2>(obj: T) { } else { obj; // T ->obj : T +>obj : T & not any[] } } diff --git a/tsc/testdata/baselines/reference/compiler/inKeywordTypeguard(strict=true).types b/tsc/testdata/baselines/reference/compiler/inKeywordTypeguard(strict=true).types index a6771860bb1fd..4fb46a70843e2 100644 --- a/tsc/testdata/baselines/reference/compiler/inKeywordTypeguard(strict=true).types +++ b/tsc/testdata/baselines/reference/compiler/inKeywordTypeguard(strict=true).types @@ -1102,14 +1102,14 @@ function test1>(obj: T) { >obj : any[] | Record >'length' in obj : boolean >'length' : "length" ->obj : T +>obj : T & not any[] obj; // T >obj : T } else { obj; // T ->obj : T +>obj : T & not any[] } } @@ -1129,7 +1129,7 @@ function test2>(obj: T) { } else { obj; // T ->obj : T +>obj : T & not any[] } } diff --git a/tsc/testdata/baselines/reference/compiler/inferTypePredicates.types b/tsc/testdata/baselines/reference/compiler/inferTypePredicates.types index 0ffd72e1e0215..ce9eea8706d04 100644 --- a/tsc/testdata/baselines/reference/compiler/inferTypePredicates.types +++ b/tsc/testdata/baselines/reference/compiler/inferTypePredicates.types @@ -548,7 +548,7 @@ if (isDate(maybeDate)) { } else { let t: object = maybeDate; // should ok >t : object ->maybeDate : object +>maybeDate : object & not Date } if (flakyIsDate(maybeDate)) { @@ -875,7 +875,7 @@ function isNumOrStr(x: unknown) { >"number" : "number" >typeof x === "string" : boolean >typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->x : unknown +>x : not number >"string" : "string" } declare let unk: unknown; diff --git a/tsc/testdata/baselines/reference/compiler/instanceofWithStructurallyIdenticalTypes.types b/tsc/testdata/baselines/reference/compiler/instanceofWithStructurallyIdenticalTypes.types index 2aacba6f3e991..6d336961bc373 100644 --- a/tsc/testdata/baselines/reference/compiler/instanceofWithStructurallyIdenticalTypes.types +++ b/tsc/testdata/baselines/reference/compiler/instanceofWithStructurallyIdenticalTypes.types @@ -93,12 +93,12 @@ function foo2(x: C1 | C2 | C3): string { else if (isC2(x)) { >isC2(x) : boolean >isC2 : (c: C1 | C2 | C3) => c is C2 ->x : C2 +>x : C2 & not C1 return x.item[0]; >x.item[0] : string >x.item : string[] ->x : C2 +>x : C2 & not C1 >item : string[] >0 : 0 } diff --git a/tsc/testdata/baselines/reference/compiler/literalFreshnessPropagationOnNarrowing.types b/tsc/testdata/baselines/reference/compiler/literalFreshnessPropagationOnNarrowing.types index ed7eeae9276ad..18929925fc104 100644 --- a/tsc/testdata/baselines/reference/compiler/literalFreshnessPropagationOnNarrowing.types +++ b/tsc/testdata/baselines/reference/compiler/literalFreshnessPropagationOnNarrowing.types @@ -71,7 +71,7 @@ function f2() { >elOrA : (string | false)[] | (string | false) >elOrA : (string | false)[] >[elOrA] : (string | false)[] ->elOrA : string | false +>elOrA : (string | false) & not any[] // Desired: OK // 3.0: Error @@ -88,7 +88,7 @@ function f2() { >elOrA : (string | false)[] | (string | false) >elOrA : (string | false)[] >[elOrA] : (string | false)[] ->elOrA : string | false +>elOrA : (string | false) & not any[] } function f3() { diff --git a/tsc/testdata/baselines/reference/compiler/narrowByBooleanComparison.types b/tsc/testdata/baselines/reference/compiler/narrowByBooleanComparison.types index 0c0ca36f17f28..9b4f12bb18471 100644 --- a/tsc/testdata/baselines/reference/compiler/narrowByBooleanComparison.types +++ b/tsc/testdata/baselines/reference/compiler/narrowByBooleanComparison.types @@ -153,7 +153,7 @@ function test3(foo: unknown) { >Array.isArray : (arg: any) => arg is any[] >Array : ArrayConstructor >isArray : (arg: any) => arg is any[] ->foo : unknown +>foo : not string >false : false throw new Error('Not a string or an array'); @@ -162,7 +162,7 @@ function test3(foo: unknown) { >'Not a string or an array' : "Not a string or an array" } foo; ->foo : string | any[] +>foo : string | (not string & any[]) } // https://github.com/microsoft/TypeScript/issues/55395 @@ -241,7 +241,7 @@ function test5(bin: Entity) { >false : false bin; ->bin : Entity +>bin : Entity & not Actor } else { bin; @@ -260,7 +260,7 @@ function test6(bin: Entity) { >false : false bin; ->bin : Entity +>bin : Entity & not Actor } else { bin; diff --git a/tsc/testdata/baselines/reference/compiler/narrowByClauseExpressionInSwitchTrue1.types b/tsc/testdata/baselines/reference/compiler/narrowByClauseExpressionInSwitchTrue1.types index 2b3a0d3605fd2..437225d559187 100644 --- a/tsc/testdata/baselines/reference/compiler/narrowByClauseExpressionInSwitchTrue1.types +++ b/tsc/testdata/baselines/reference/compiler/narrowByClauseExpressionInSwitchTrue1.types @@ -140,7 +140,7 @@ function processInput(input: string | RegExp | SomeType) { >RegExp : RegExpConstructor input; ->input : RegExp +>input : RegExp & not string break; case isSomeType(input): @@ -149,7 +149,7 @@ function processInput(input: string | RegExp | SomeType) { >input : string | RegExp | SomeType input; ->input : SomeType +>input : SomeType & not string break; } diff --git a/tsc/testdata/baselines/reference/compiler/narrowUnknownByTypePredicate.types b/tsc/testdata/baselines/reference/compiler/narrowUnknownByTypePredicate.types index 26d83a9a4305d..1604843a968a5 100644 --- a/tsc/testdata/baselines/reference/compiler/narrowUnknownByTypePredicate.types +++ b/tsc/testdata/baselines/reference/compiler/narrowUnknownByTypePredicate.types @@ -89,6 +89,6 @@ if (!isA(value6)) { >value6 : unknown value6; ->value6 : unknown +>value6 : not A } diff --git a/tsc/testdata/baselines/reference/compiler/narrowingAssignmentReadonlyRespectsAssertion.types b/tsc/testdata/baselines/reference/compiler/narrowingAssignmentReadonlyRespectsAssertion.types index 7e9b569d55f82..ad7900e57702d 100644 --- a/tsc/testdata/baselines/reference/compiler/narrowingAssignmentReadonlyRespectsAssertion.types +++ b/tsc/testdata/baselines/reference/compiler/narrowingAssignmentReadonlyRespectsAssertion.types @@ -131,7 +131,7 @@ function testFunc() { >console.log : (...data: any[]) => void >console : Console >log : (...data: any[]) => void ->val1 : string | number | readonly (string | number)[] +>val1 : (string | number | readonly (string | number)[]) & not any[] } console.log(val2); >console.log(val2) : void diff --git a/tsc/testdata/baselines/reference/compiler/narrowingByTypeofInSwitch.types b/tsc/testdata/baselines/reference/compiler/narrowingByTypeofInSwitch.types index 4a5fcccf8c46a..6ccbbd2f4429c 100644 --- a/tsc/testdata/baselines/reference/compiler/narrowingByTypeofInSwitch.types +++ b/tsc/testdata/baselines/reference/compiler/narrowingByTypeofInSwitch.types @@ -866,7 +866,7 @@ function narrowingNarrows(x: {} | undefined) { default: const _y: {} = x; return; >_y : {} ->x : {} +>x : {} & not number & not false & not true & not symbol & not string } } diff --git a/tsc/testdata/baselines/reference/compiler/narrowingMutualSubtypes.errors.txt b/tsc/testdata/baselines/reference/compiler/narrowingMutualSubtypes.errors.txt index ada909330f3eb..3df86a44d8564 100644 --- a/tsc/testdata/baselines/reference/compiler/narrowingMutualSubtypes.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/narrowingMutualSubtypes.errors.txt @@ -1,7 +1,7 @@ -narrowingMutualSubtypes.ts(117,17): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'any[] | Record'. - No index signature with a parameter of type 'string' was found on type 'any[] | Record'. -narrowingMutualSubtypes.ts(118,29): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'any[] | Record'. - No index signature with a parameter of type 'string' was found on type 'any[] | Record'. +narrowingMutualSubtypes.ts(117,17): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record[] | Record'. + No index signature with a parameter of type 'string' was found on type 'Record[] | Record'. +narrowingMutualSubtypes.ts(118,29): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record[] | Record'. + No index signature with a parameter of type 'string' was found on type 'Record[] | Record'. ==== narrowingMutualSubtypes.ts (2 errors) ==== @@ -123,12 +123,12 @@ narrowingMutualSubtypes.ts(118,29): error TS7053: Element implicitly has an 'any for (let key in obj) { if (obj[key] !== undefined) { ~~~~~~~~ -!!! error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'any[] | Record'. -!!! error TS7053: No index signature with a parameter of type 'string' was found on type 'any[] | Record'. +!!! error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record[] | Record'. +!!! error TS7053: No index signature with a parameter of type 'string' was found on type 'Record[] | Record'. console.log(obj[key]) ~~~~~~~~ -!!! error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'any[] | Record'. -!!! error TS7053: No index signature with a parameter of type 'string' was found on type 'any[] | Record'. +!!! error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record[] | Record'. +!!! error TS7053: No index signature with a parameter of type 'string' was found on type 'Record[] | Record'. } } } diff --git a/tsc/testdata/baselines/reference/compiler/narrowingMutualSubtypes.types b/tsc/testdata/baselines/reference/compiler/narrowingMutualSubtypes.types index f47c641078a87..93b61bbedadca 100644 --- a/tsc/testdata/baselines/reference/compiler/narrowingMutualSubtypes.types +++ b/tsc/testdata/baselines/reference/compiler/narrowingMutualSubtypes.types @@ -105,10 +105,10 @@ function gg1(x: {}) { } else { x; // {} ->x : {} +>x : never } x; // {} ->x : {} +>x : Record } declare function isObject2(value: unknown): value is {}; @@ -155,10 +155,10 @@ function gg3(x: {}) { } else { x; // {} ->x : {} +>x : never } x; // {} ->x : {} +>x : Record } declare function isObject4(value: unknown): value is {}; @@ -297,12 +297,12 @@ function checksArrayOrObject1(obj: Record | Record[]) // 'obj' should probably not include an array type here. for (let key in obj) { >key : string ->obj : any[] | Record +>obj : Record[] | Record if (obj[key] !== undefined) { >obj[key] !== undefined : boolean >obj[key] : any ->obj : any[] | Record +>obj : Record[] | Record >key : string >undefined : undefined @@ -312,7 +312,7 @@ function checksArrayOrObject1(obj: Record | Record[]) >console : Console >log : (...data: any[]) => void >obj[key] : any ->obj : any[] | Record +>obj : Record[] | Record >key : string } } @@ -357,12 +357,12 @@ function checksArrayOrObject2(obj: Record | Record[]) // 'obj' should probably not include an array type here. for (let key in obj) { >key : string ->obj : Record +>obj : Record & not any[] if (obj[key] !== undefined) { >obj[key] !== undefined : boolean >obj[key] : any ->obj : Record +>obj : Record & not any[] >key : string >undefined : undefined @@ -372,7 +372,7 @@ function checksArrayOrObject2(obj: Record | Record[]) >console : Console >log : (...data: any[]) => void >obj[key] : any ->obj : Record +>obj : Record & not any[] >key : string } } diff --git a/tsc/testdata/baselines/reference/compiler/narrowingOfDottedNames.types b/tsc/testdata/baselines/reference/compiler/narrowingOfDottedNames.types index 87b06317015d9..27397c406ab5c 100644 --- a/tsc/testdata/baselines/reference/compiler/narrowingOfDottedNames.types +++ b/tsc/testdata/baselines/reference/compiler/narrowingOfDottedNames.types @@ -95,12 +95,12 @@ function f2(x: A | B) { else if (isB(x)) { >isB(x) : boolean >isB : (x: any) => x is B ->x : B +>x : B & not A x.prop.b; >x.prop.b : string >x.prop : { b: string; } ->x : B +>x : B & not A >prop : { b: string; } >b : string } diff --git a/tsc/testdata/baselines/reference/compiler/narrowingPastLastAssignment.types b/tsc/testdata/baselines/reference/compiler/narrowingPastLastAssignment.types index c690c529a0dca..6ca11e6d1daba 100644 --- a/tsc/testdata/baselines/reference/compiler/narrowingPastLastAssignment.types +++ b/tsc/testdata/baselines/reference/compiler/narrowingPastLastAssignment.types @@ -252,14 +252,14 @@ function f5b() { >x : number >1 : 1 >x === 2 : boolean ->x : number +>x : number & not 1 >2 : 2 action(() => { x /* 1 | 2 */ }) >action(() => { x /* 1 | 2 */ }) : void >action : (f: Function) => void >() => { x /* 1 | 2 */ } : () => void ->x : 1 | 2 +>x : number } } } diff --git a/tsc/testdata/baselines/reference/compiler/narrowingUnionToUnion.types b/tsc/testdata/baselines/reference/compiler/narrowingUnionToUnion.types index c95edf9e1ea81..ed84810388b8b 100644 --- a/tsc/testdata/baselines/reference/compiler/narrowingUnionToUnion.types +++ b/tsc/testdata/baselines/reference/compiler/narrowingUnionToUnion.types @@ -229,7 +229,7 @@ const TEST_CASES = [ } else { value; // string ->value : string +>value : string & not "" } if (isMaybeEmptyString(value)) { >isMaybeEmptyString(value) : boolean @@ -241,7 +241,7 @@ const TEST_CASES = [ } else { value; // string ->value : string +>value : string & not "" } }, (value?: string) => { @@ -258,7 +258,7 @@ const TEST_CASES = [ } else { value; // string ->value : string +>value : string & not "" } }, (value: number) => { @@ -275,7 +275,7 @@ const TEST_CASES = [ } else { value; // number ->value : number +>value : number & not 0 } if (isMaybeZero(value)) { >isMaybeZero(value) : boolean @@ -287,7 +287,7 @@ const TEST_CASES = [ } else { value; // number ->value : number +>value : number & not 0 } }, (value?: number) => { @@ -304,7 +304,7 @@ const TEST_CASES = [ } else { value; // number ->value : number +>value : number & not 0 } }, (value: string[]) => { @@ -321,7 +321,7 @@ const TEST_CASES = [ } else { value; // string[] ->value : string[] +>value : string[] & not [] } if (isMaybeEmptyArray(value)) { >isMaybeEmptyArray(value) : boolean @@ -333,7 +333,7 @@ const TEST_CASES = [ } else { value; // string[] ->value : string[] +>value : string[] & not [] } }, (value?: string[]) => { @@ -350,7 +350,7 @@ const TEST_CASES = [ } else { value; // string[] ->value : string[] +>value : string[] & not [] } }, ]; @@ -371,9 +371,9 @@ function isEmpty(value: string | EmptyString): value is EmptyString { >value : string | null | undefined >'' : "" >value === null : boolean ->value : string | null | undefined +>value : (string & not "") | null | undefined >value === undefined : boolean ->value : string | undefined +>value : (string & not "") | undefined >undefined : undefined } @@ -421,7 +421,7 @@ function check1(x: unknown): x is (string | 0) { >x : unknown >"string" : "string" >x === 0 : boolean ->x : unknown +>x : not string >0 : 0 } @@ -435,7 +435,7 @@ function check2(x: unknown): x is ("hello" | 0) { >x : unknown >"hello" : "hello" >x === 0 : boolean ->x : unknown +>x : not "hello" >0 : 0 } @@ -450,7 +450,7 @@ function test3(x: unknown) { >x : unknown >"string" : "string" >x === 0 : boolean ->x : unknown +>x : not string >0 : 0 x; // string | 0 @@ -462,11 +462,11 @@ function test3(x: unknown) { >x : string | 0 >"hello" : "hello" >x === 0 : boolean ->x : string | 0 +>x : 0 | (string & not "hello") >0 : 0 x; // 0 | "hello" ->x : "hello" | 0 +>x : string | 0 } } if (check1(x)) { diff --git a/tsc/testdata/baselines/reference/compiler/noIterationTypeErrorsInCFA.types b/tsc/testdata/baselines/reference/compiler/noIterationTypeErrorsInCFA.types index cd55499d9c629..b9d969eab5471 100644 --- a/tsc/testdata/baselines/reference/compiler/noIterationTypeErrorsInCFA.types +++ b/tsc/testdata/baselines/reference/compiler/noIterationTypeErrorsInCFA.types @@ -21,7 +21,7 @@ export function doRemove(dds: F | F[]) { >dds = [dds] : F[] >dds : F[] | F >[dds] : F[] ->dds : F +>dds : F & not any[] } for (let n of dds) { >n : F diff --git a/tsc/testdata/baselines/reference/compiler/observableInferenceCanBeMade.types b/tsc/testdata/baselines/reference/compiler/observableInferenceCanBeMade.types index 9a393f5098c25..329c335d790e1 100644 --- a/tsc/testdata/baselines/reference/compiler/observableInferenceCanBeMade.types +++ b/tsc/testdata/baselines/reference/compiler/observableInferenceCanBeMade.types @@ -54,6 +54,6 @@ function asObservable(input: string | ObservableInput): Observableinput : string >from(input) : Observable >from : >(input: O) => Observable> ->input : ObservableInput +>input : ObservableInput & not string } diff --git a/tsc/testdata/baselines/reference/compiler/quickinfoTypeAtReturnPositionsInaccurate.types b/tsc/testdata/baselines/reference/compiler/quickinfoTypeAtReturnPositionsInaccurate.types index 404c8aa713405..07380273e8a74 100644 --- a/tsc/testdata/baselines/reference/compiler/quickinfoTypeAtReturnPositionsInaccurate.types +++ b/tsc/testdata/baselines/reference/compiler/quickinfoTypeAtReturnPositionsInaccurate.types @@ -99,7 +99,7 @@ class SimpleStore | StrClass } return entry; // type is Entries[EntryId] - all fine ->entry : Entries[EntryId] +>entry : Entries[EntryId] & not Extract> } } @@ -159,7 +159,7 @@ class ComplexStore { item.get(); >item.get() : string | number >item.get : (() => number) | (() => string) ->item : NumClass | StrClass +>item : NumClass | (StrClass & not Extract>) >get : (() => number) | (() => string) // unfortunately, doesn't work completely. @@ -201,11 +201,11 @@ class ComplexStore { item.get(); >item.get() : string | number >item.get : (() => number) | (() => string) ->item : NumClass | StrClass +>item : (NumClass | StrClass) & not Extract> >get : (() => number) | (() => string) return item; // type is never ->item : Slices[SliceId][SliceKey] +>item : Slices[SliceId][SliceKey] & not Extract> } } @@ -236,5 +236,5 @@ export function listFiles(program: Program | T) { >program.getProgram : () => Program >program : T >getProgram : () => Program ->program : Program +>program : Program & not T } diff --git a/tsc/testdata/baselines/reference/compiler/recursiveTypeRelations.types b/tsc/testdata/baselines/reference/compiler/recursiveTypeRelations.types index a0b0cc1fbbc75..14eca81415b4d 100644 --- a/tsc/testdata/baselines/reference/compiler/recursiveTypeRelations.types +++ b/tsc/testdata/baselines/reference/compiler/recursiveTypeRelations.types @@ -65,7 +65,7 @@ export function css(styles: S, ...classNam if (typeof arg == "object") { >typeof arg == "object" : boolean >typeof arg : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->arg : ClassNameArg +>arg : ClassNameArg & not string >"object" : "object" return Object.keys(arg).reduce((obj: ClassNameObject, key: keyof S) => { @@ -95,7 +95,7 @@ export function css(styles: S, ...classNam >(arg as ClassNameMap)[key] : boolean | undefined >(arg as ClassNameMap) : ClassNameMap >arg as ClassNameMap : ClassNameMap ->arg : ClassNameObjectMap +>arg : object & ClassNameMap >key : keyof S return obj; diff --git a/tsc/testdata/baselines/reference/compiler/simpleRecursionWithBaseCase1.types b/tsc/testdata/baselines/reference/compiler/simpleRecursionWithBaseCase1.types index e05a9c8542267..3c9ca0f6e6cd4 100644 --- a/tsc/testdata/baselines/reference/compiler/simpleRecursionWithBaseCase1.types +++ b/tsc/testdata/baselines/reference/compiler/simpleRecursionWithBaseCase1.types @@ -18,7 +18,7 @@ function fn1(n: number) { >fn1(n - 1) : number >fn1 : (n: number) => number >n - 1 : number ->n : number +>n : number & not 0 >1 : 1 } } diff --git a/tsc/testdata/baselines/reference/compiler/spreadBooleanRespectsFreshness.types b/tsc/testdata/baselines/reference/compiler/spreadBooleanRespectsFreshness.types index 012fe89cff812..26898696c28df 100644 --- a/tsc/testdata/baselines/reference/compiler/spreadBooleanRespectsFreshness.types +++ b/tsc/testdata/baselines/reference/compiler/spreadBooleanRespectsFreshness.types @@ -18,17 +18,17 @@ declare let foo2: Foo; >foo2 : Foo foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]]; ->foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]] : FooBase[] +>foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]] : (string | false)[] >foo1 : Foo ->[...Array.isArray(foo2) ? foo2 : [foo2]] : FooBase[] ->...Array.isArray(foo2) ? foo2 : [foo2] : FooBase ->Array.isArray(foo2) ? foo2 : [foo2] : FooBase[] +>[...Array.isArray(foo2) ? foo2 : [foo2]] : (string | false)[] +>...Array.isArray(foo2) ? foo2 : [foo2] : string | false +>Array.isArray(foo2) ? foo2 : [foo2] : (string | false)[] >Array.isArray(foo2) : boolean >Array.isArray : (arg: any) => arg is any[] >Array : ArrayConstructor >isArray : (arg: any) => arg is any[] >foo2 : Foo >foo2 : FooArray ->[foo2] : FooBase[] ->foo2 : FooBase +>[foo2] : (string | false)[] +>foo2 : FooBase & not any[] diff --git a/tsc/testdata/baselines/reference/compiler/strictSubtypeAndNarrowing.types b/tsc/testdata/baselines/reference/compiler/strictSubtypeAndNarrowing.types index b1fe4d2e399f3..75c5fc5fd5205 100644 --- a/tsc/testdata/baselines/reference/compiler/strictSubtypeAndNarrowing.types +++ b/tsc/testdata/baselines/reference/compiler/strictSubtypeAndNarrowing.types @@ -210,10 +210,10 @@ function checkA(f: FnTypes) { } else { f; // C | D ->f : C | D +>f : (C | D) & not A } f; // FnTypes ->f : FnTypes +>f : C } function checkB(f: FnTypes) { @@ -230,10 +230,10 @@ function checkB(f: FnTypes) { } else { f; // C | D ->f : C | D +>f : (C | D) & not B } f; // FnTypes ->f : FnTypes +>f : C } function checkC(f: FnTypes) { @@ -397,10 +397,10 @@ function ff3(value: string | string[] | { [index: number]: boolean, length: numb } else { value; ->value : number | { length: string; } | { a: string; } | null | undefined +>value : (number | { length: string; } | { a: string; } | null | undefined) & not { length: number; } } value; ->value : string | number | string[] | { [index: number]: boolean; length: number; } | { length: string; } | { a: string; } | [number, boolean] | null | undefined +>value : string | string[] | { [index: number]: boolean; length: number; } | [number, boolean] | ((number | { length: string; } | { a: string; } | null | undefined) & not { length: number; }) } // Repro from comment in #52984 @@ -512,7 +512,7 @@ function test2(foo: Foo): {value: {type: 'A'}; a?: number} { >isB : (arg: unknown) => arg is 'B' return foo; ->foo : { value: { type: 'A'; }; a?: number; } +>foo : { value: { type: 'A'; }; a?: number; } & not ({ value: { type: 'B'; }; b?: number; } & Readonly>>>) } // Repro from #53063 @@ -553,7 +553,7 @@ const f = (value: Union) => { value.premium; >value.premium : false ->value : { premium: false; } +>value : { premium: false; } & not never >premium : false } }; diff --git a/tsc/testdata/baselines/reference/compiler/typePredicateStructuralMatch.types b/tsc/testdata/baselines/reference/compiler/typePredicateStructuralMatch.types index 25a4ab8d5476c..00f580ecc9ed4 100644 --- a/tsc/testdata/baselines/reference/compiler/typePredicateStructuralMatch.types +++ b/tsc/testdata/baselines/reference/compiler/typePredicateStructuralMatch.types @@ -61,7 +61,7 @@ function getResults1(value: Results | { data: Results }): Results { >value.data : Results >value : { data: Results; } >data : Results ->value : Results +>value : Results & not { data: Results; } } function isPlainResponse(value: T | { data: T}): value is T { @@ -90,6 +90,6 @@ function getResults2(value: Results | { data: Results }): Results { >value : Results | { data: Results; } >value : Results >value.data : Results ->value : { data: Results; } +>value : { data: Results; } & not Results >data : Results } diff --git a/tsc/testdata/baselines/reference/compiler/typePredicateWithThisParameter.types b/tsc/testdata/baselines/reference/compiler/typePredicateWithThisParameter.types index 26fcf19851d8c..a8a7309692768 100644 --- a/tsc/testdata/baselines/reference/compiler/typePredicateWithThisParameter.types +++ b/tsc/testdata/baselines/reference/compiler/typePredicateWithThisParameter.types @@ -52,7 +52,7 @@ if (isFoo1(test)) { if (isFoo2(test)) { >isFoo2(test) : boolean >isFoo2 : (this: void, object: {}) => object is Foo ->test : Bar | Foo +>test : Foo | (Bar & not Foo) test.foo = 'hi'; >test.foo = 'hi' : "hi" diff --git a/tsc/testdata/baselines/reference/compiler/typeVariableTypeGuards.types b/tsc/testdata/baselines/reference/compiler/typeVariableTypeGuards.types index 7b6b1c15f6716..5e09694db2908 100644 --- a/tsc/testdata/baselines/reference/compiler/typeVariableTypeGuards.types +++ b/tsc/testdata/baselines/reference/compiler/typeVariableTypeGuards.types @@ -214,7 +214,7 @@ function f6 {})>(a: T) { new a(); >new a() : {} ->a : new () => {} +>a : (new () => {}) & not string } } diff --git a/tsc/testdata/baselines/reference/compiler/unreachableSwitchTypeofUnknown.types b/tsc/testdata/baselines/reference/compiler/unreachableSwitchTypeofUnknown.types index dd7772b049645..2f2604dd0624f 100644 --- a/tsc/testdata/baselines/reference/compiler/unreachableSwitchTypeofUnknown.types +++ b/tsc/testdata/baselines/reference/compiler/unreachableSwitchTypeofUnknown.types @@ -43,5 +43,5 @@ const unreachable = (x: unknown): number => { >0 : 0 } x; ->x : unknown +>x : not string & not number & not bigint & not false & not true & not symbol & not undefined } diff --git a/tsc/testdata/baselines/reference/compiler/unusedPrivateStaticMembers.types b/tsc/testdata/baselines/reference/compiler/unusedPrivateStaticMembers.types index 0362756de5ee2..9b4ac44843ec9 100644 --- a/tsc/testdata/baselines/reference/compiler/unusedPrivateStaticMembers.types +++ b/tsc/testdata/baselines/reference/compiler/unusedPrivateStaticMembers.types @@ -62,13 +62,13 @@ class Test4 { >1 : 1 >(n * Test4.m1(n - 1)) : number >n * Test4.m1(n - 1) : number ->n : number +>n : number & not 0 >Test4.m1(n - 1) : number >Test4.m1 : (n: number) => number >Test4 : typeof Test4 >m1 : (n: number) => number >n - 1 : number ->n : number +>n : number & not 0 >1 : 1 } @@ -85,13 +85,13 @@ class Test4 { >1 : 1 >(n * Test4["m2"](n - 1)) : number >n * Test4["m2"](n - 1) : number ->n : number +>n : number & not 0 >Test4["m2"](n - 1) : number >Test4["m2"] : (n: number) => number >Test4 : typeof Test4 >"m2" : "m2" >n - 1 : number ->n : number +>n : number & not 0 >1 : 1 } } diff --git a/tsc/testdata/baselines/reference/compiler/weakTypeAndPrimitiveNarrowing.types b/tsc/testdata/baselines/reference/compiler/weakTypeAndPrimitiveNarrowing.types index 73be78dbed279..3a93c1c2ca820 100644 --- a/tsc/testdata/baselines/reference/compiler/weakTypeAndPrimitiveNarrowing.types +++ b/tsc/testdata/baselines/reference/compiler/weakTypeAndPrimitiveNarrowing.types @@ -32,7 +32,7 @@ const g = (arg: LiteralsAndWeakTypes) => { } else { arg; ->arg : "B" | { optional?: true; } | { toLowerCase?(): string; } | { toUpperCase?(): string; otherOptionalProp?: number; } +>arg : ("B" | { optional?: true; } | { toLowerCase?(): string; } | { toUpperCase?(): string; otherOptionalProp?: number; }) & not "A" } } @@ -67,7 +67,7 @@ const h = (arg: PrimitivesAndWeakTypes) => { } else { arg; ->arg : PrimitivesAndWeakTypes +>arg : PrimitivesAndWeakTypes & not "A" } } diff --git a/tsc/testdata/baselines/reference/conformance/TypeGuardWithEnumUnion.types b/tsc/testdata/baselines/reference/conformance/TypeGuardWithEnumUnion.types index fddfa9db658ef..94fc8baeaf053 100644 --- a/tsc/testdata/baselines/reference/conformance/TypeGuardWithEnumUnion.types +++ b/tsc/testdata/baselines/reference/conformance/TypeGuardWithEnumUnion.types @@ -67,7 +67,7 @@ function f2(x: Color | string | string[]) { else { var w = x; >w : string | string[] ->x : string | string[] +>x : string | (string[] & not number) var w: string | string[]; >w : string | string[] @@ -75,7 +75,7 @@ function f2(x: Color | string | string[]) { if (typeof x === "string") { >typeof x === "string" : boolean >typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->x : string | string[] | Color +>x : string | Color | (string[] & not number) >"string" : "string" var a = x; @@ -87,11 +87,11 @@ function f2(x: Color | string | string[]) { } else { var b = x; ->b : string[] | Color ->x : string[] | Color +>b : Color | string[] +>x : (Color | (string[] & not number)) & not string var b: Color | string[]; ->b : string[] | Color +>b : Color | string[] } } diff --git a/tsc/testdata/baselines/reference/conformance/assertionTypePredicates1.types b/tsc/testdata/baselines/reference/conformance/assertionTypePredicates1.types index 2295fc2e0634c..bbd8d4e865523 100644 --- a/tsc/testdata/baselines/reference/conformance/assertionTypePredicates1.types +++ b/tsc/testdata/baselines/reference/conformance/assertionTypePredicates1.types @@ -81,7 +81,7 @@ function f01(x: unknown) { >"boolean" : "boolean" >typeof x === "number" : boolean >typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->x : unknown +>x : not false & not true >"number" : "number" x.toLocaleString; diff --git a/tsc/testdata/baselines/reference/conformance/classStaticBlock8.types b/tsc/testdata/baselines/reference/conformance/classStaticBlock8.types index 967a461b2c92d..4ab4feb362b0d 100644 --- a/tsc/testdata/baselines/reference/conformance/classStaticBlock8.types +++ b/tsc/testdata/baselines/reference/conformance/classStaticBlock8.types @@ -56,7 +56,7 @@ function foo (v: number) { } if (v === 6) { >v === 6 : boolean ->v : number +>v : number & not 5 >6 : 6 continue label; @@ -64,14 +64,14 @@ function foo (v: number) { } if (v === 7) { >v === 7 : boolean ->v : number +>v : number & not 5 & not 6 >7 : 7 break; } if (v === 8) { >v === 8 : boolean ->v : number +>v : number & not 5 & not 6 & not 7 >8 : 8 continue; @@ -98,18 +98,18 @@ function foo (v: number) { if (v === 2) continue loop; // valid >v === 2 : boolean ->v : number +>v : number & not 1 >2 : 2 >loop : any if (v === 3) break; // valid >v === 3 : boolean ->v : number +>v : number & not 1 & not 2 >3 : 3 if (v === 4) continue; // valid >v === 4 : boolean ->v : number +>v : number & not 1 & not 2 & not 3 >4 : 4 } switch (v) { diff --git a/tsc/testdata/baselines/reference/conformance/conditionalTypes1.types b/tsc/testdata/baselines/reference/conformance/conditionalTypes1.types index b5496f00171d2..28adb6626eac6 100644 --- a/tsc/testdata/baselines/reference/conformance/conditionalTypes1.types +++ b/tsc/testdata/baselines/reference/conformance/conditionalTypes1.types @@ -421,7 +421,7 @@ function zeroOf(value: T) { >typeof value === "string" ? "" : false : "" | false >typeof value === "string" : boolean >typeof value : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->value : T +>value : T & not number >"string" : "string" >"" : "" >false : false diff --git a/tsc/testdata/baselines/reference/conformance/controlFlowBinaryOrExpression.symbols b/tsc/testdata/baselines/reference/conformance/controlFlowBinaryOrExpression.symbols index 5d72a18cfc3d5..b279b82ef6be3 100644 --- a/tsc/testdata/baselines/reference/conformance/controlFlowBinaryOrExpression.symbols +++ b/tsc/testdata/baselines/reference/conformance/controlFlowBinaryOrExpression.symbols @@ -76,9 +76,9 @@ if (isHTMLCollection(sourceObj)) { >sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3)) sourceObj.length; ->sourceObj.length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 14, 33), Decl(controlFlowBinaryOrExpression.ts, 10, 27)) +>sourceObj.length : Symbol(HTMLCollection.length, Decl(controlFlowBinaryOrExpression.ts, 14, 33)) >sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3)) ->length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 14, 33), Decl(controlFlowBinaryOrExpression.ts, 10, 27)) +>length : Symbol(HTMLCollection.length, Decl(controlFlowBinaryOrExpression.ts, 14, 33)) } if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) { diff --git a/tsc/testdata/baselines/reference/conformance/controlFlowBinaryOrExpression.types b/tsc/testdata/baselines/reference/conformance/controlFlowBinaryOrExpression.types index 63b4d58cb8be3..de5b918a396dd 100644 --- a/tsc/testdata/baselines/reference/conformance/controlFlowBinaryOrExpression.types +++ b/tsc/testdata/baselines/reference/conformance/controlFlowBinaryOrExpression.types @@ -78,11 +78,11 @@ if (isNodeList(sourceObj)) { if (isHTMLCollection(sourceObj)) { >isHTMLCollection(sourceObj) : boolean >isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection ->sourceObj : EventTargetLike +>sourceObj : HTMLCollection | ({ a: string; } & not NodeList) sourceObj.length; >sourceObj.length : number ->sourceObj : HTMLCollection | NodeList +>sourceObj : HTMLCollection >length : number } @@ -90,10 +90,10 @@ if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) { >isNodeList(sourceObj) || isHTMLCollection(sourceObj) : boolean >isNodeList(sourceObj) : boolean >isNodeList : (sourceObj: any) => sourceObj is NodeList ->sourceObj : EventTargetLike +>sourceObj : HTMLCollection | ({ a: string; } & not NodeList & not HTMLCollection) >isHTMLCollection(sourceObj) : boolean >isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection ->sourceObj : { a: string; } +>sourceObj : { a: string; } & not NodeList & not HTMLCollection sourceObj.length; >sourceObj.length : number diff --git a/tsc/testdata/baselines/reference/conformance/controlFlowElementAccess2.types b/tsc/testdata/baselines/reference/conformance/controlFlowElementAccess2.types index a6d79c72946e4..b8ee3cc036a5e 100644 --- a/tsc/testdata/baselines/reference/conformance/controlFlowElementAccess2.types +++ b/tsc/testdata/baselines/reference/conformance/controlFlowElementAccess2.types @@ -21,16 +21,16 @@ if (typeof config['works'] !== 'boolean') { config.works.prop = 'test'; // ok >config.works.prop = 'test' : "test" >config.works.prop : string ->config.works : { prop: string; } +>config.works : { prop: string; } & not false & not true >config : { [key: string]: boolean | { prop: string; }; } ->works : { prop: string; } +>works : { prop: string; } & not false & not true >prop : string >'test' : "test" config['works'].prop = 'test'; // error, config['works']: boolean | { 'prop': string } >config['works'].prop = 'test' : "test" >config['works'].prop : string ->config['works'] : { prop: string; } +>config['works'] : { prop: string; } & not false & not true >config : { [key: string]: boolean | { prop: string; }; } >'works' : "works" >prop : string @@ -39,15 +39,15 @@ if (typeof config['works'] !== 'boolean') { if (typeof config.works !== 'boolean') { >typeof config.works !== 'boolean' : boolean >typeof config.works : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->config.works : boolean | { prop: string; } +>config.works : boolean | ({ prop: string; } & not false & not true) >config : { [key: string]: boolean | { prop: string; }; } ->works : boolean | { prop: string; } +>works : boolean | ({ prop: string; } & not false & not true) >'boolean' : "boolean" config['works'].prop = 'test'; // error, config['works']: boolean | { 'prop': string } >config['works'].prop = 'test' : "test" >config['works'].prop : string ->config['works'] : { prop: string; } +>config['works'] : { prop: string; } & not false & not true >config : { [key: string]: boolean | { prop: string; }; } >'works' : "works" >prop : string @@ -56,9 +56,9 @@ if (typeof config.works !== 'boolean') { config.works.prop = 'test'; // ok >config.works.prop = 'test' : "test" >config.works.prop : string ->config.works : { prop: string; } +>config.works : { prop: string; } & not false & not true >config : { [key: string]: boolean | { prop: string; }; } ->works : { prop: string; } +>works : { prop: string; } & not false & not true >prop : string >'test' : "test" } diff --git a/tsc/testdata/baselines/reference/conformance/controlFlowGenericTypes.types b/tsc/testdata/baselines/reference/conformance/controlFlowGenericTypes.types index 35210bb1d241e..9bee274276ffb 100644 --- a/tsc/testdata/baselines/reference/conformance/controlFlowGenericTypes.types +++ b/tsc/testdata/baselines/reference/conformance/controlFlowGenericTypes.types @@ -190,7 +190,7 @@ export function bounceAndTakeIfA(value: AB): AB { } else { return value; ->value : AB +>value : AB & not "A" } } diff --git a/tsc/testdata/baselines/reference/conformance/controlFlowIfStatement.types b/tsc/testdata/baselines/reference/conformance/controlFlowIfStatement.types index 37fb95fca1090..689327f6e38ea 100644 --- a/tsc/testdata/baselines/reference/conformance/controlFlowIfStatement.types +++ b/tsc/testdata/baselines/reference/conformance/controlFlowIfStatement.types @@ -110,7 +110,7 @@ function c(data: string | T): T { } else { return data; ->data : T +>data : T & not string } } function d(data: string | T): never { diff --git a/tsc/testdata/baselines/reference/conformance/fixSignatureCaching.types b/tsc/testdata/baselines/reference/conformance/fixSignatureCaching.types index c74656913b9fd..1010dd08d8d40 100644 --- a/tsc/testdata/baselines/reference/conformance/fixSignatureCaching.types +++ b/tsc/testdata/baselines/reference/conformance/fixSignatureCaching.types @@ -3413,7 +3413,7 @@ define(function () { >window : Window & typeof globalThis >'undefined' : "undefined" >window.screen : Screen ->window : Window & typeof globalThis +>window : Window & typeof globalThis & not undefined >screen : Screen MobileDetect.isPhoneSized = function (maxPhoneWidth) { diff --git a/tsc/testdata/baselines/reference/conformance/literalTypes3.types b/tsc/testdata/baselines/reference/conformance/literalTypes3.types index 3841da4e52fbc..be3fbb9f1ac50 100644 --- a/tsc/testdata/baselines/reference/conformance/literalTypes3.types +++ b/tsc/testdata/baselines/reference/conformance/literalTypes3.types @@ -19,11 +19,11 @@ function f1(s: string) { >s : string >"foo" : "foo" >s === "bar" : boolean ->s : string +>s : string & not "foo" >"bar" : "bar" s; // "foo" | "bar" ->s : "bar" | "foo" +>s : string } } @@ -57,24 +57,24 @@ function f2(s: string) { } function f3(s: string) { ->f3 : (s: string) => "bar" | "foo" | undefined +>f3 : (s: string) => string | undefined >s : string return s === "foo" || s === "bar" ? s : undefined; // "foo" | "bar" | undefined ->s === "foo" || s === "bar" ? s : undefined : "bar" | "foo" | undefined +>s === "foo" || s === "bar" ? s : undefined : string | undefined >s === "foo" || s === "bar" : boolean >s === "foo" : boolean >s : string >"foo" : "foo" >s === "bar" : boolean ->s : string +>s : string & not "foo" >"bar" : "bar" ->s : "bar" | "foo" +>s : string >undefined : undefined } function f4(x: number) { ->f4 : (x: number) => 1 | 2 +>f4 : (x: number) => number >x : number if (x === 1 || x === 2) { @@ -83,11 +83,11 @@ function f4(x: number) { >x : number >1 : 1 >x === 2 : boolean ->x : number +>x : number & not 1 >2 : 2 return x; // 1 | 2 ->x : 1 | 2 +>x : number } throw new Error(); >new Error() : Error @@ -105,11 +105,11 @@ function f5(x: number, y: 1 | 2) { >x : number >0 : 0 >x === y : boolean ->x : number +>x : number & not 0 >y : 1 | 2 x; // 0 | 1 | 2 ->x : 0 | 1 | 2 +>x : number } } diff --git a/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2015).types b/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2015).types index 4b49ca75ffcf4..f24afa835548a 100644 --- a/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2015).types +++ b/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2015).types @@ -100,7 +100,7 @@ function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue } else if (v === 2) { >v === 2 : boolean ->v : number +>v : number & not 1 >2 : 2 if (thing &&= defaultValue) { @@ -121,7 +121,7 @@ function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue } else if (v === 3) { >v === 3 : boolean ->v : number +>v : number & not 1 & not 2 >3 : 3 if (thing ||= defaultValue) { diff --git a/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2020).types b/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2020).types index 4b49ca75ffcf4..f24afa835548a 100644 --- a/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2020).types +++ b/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2020).types @@ -100,7 +100,7 @@ function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue } else if (v === 2) { >v === 2 : boolean ->v : number +>v : number & not 1 >2 : 2 if (thing &&= defaultValue) { @@ -121,7 +121,7 @@ function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue } else if (v === 3) { >v === 3 : boolean ->v : number +>v : number & not 1 & not 2 >3 : 3 if (thing ||= defaultValue) { diff --git a/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2021).types b/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2021).types index 4b49ca75ffcf4..f24afa835548a 100644 --- a/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2021).types +++ b/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=es2021).types @@ -100,7 +100,7 @@ function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue } else if (v === 2) { >v === 2 : boolean ->v : number +>v : number & not 1 >2 : 2 if (thing &&= defaultValue) { @@ -121,7 +121,7 @@ function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue } else if (v === 3) { >v === 3 : boolean ->v : number +>v : number & not 1 & not 2 >3 : 3 if (thing ||= defaultValue) { diff --git a/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=esnext).types b/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=esnext).types index 4b49ca75ffcf4..f24afa835548a 100644 --- a/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=esnext).types +++ b/tsc/testdata/baselines/reference/conformance/logicalAssignment4(target=esnext).types @@ -100,7 +100,7 @@ function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue } else if (v === 2) { >v === 2 : boolean ->v : number +>v : number & not 1 >2 : 2 if (thing &&= defaultValue) { @@ -121,7 +121,7 @@ function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue } else if (v === 3) { >v === 3 : boolean ->v : number +>v : number & not 1 & not 2 >3 : 3 if (thing ||= defaultValue) { diff --git a/tsc/testdata/baselines/reference/conformance/negatedDiscriminantIntersectionSimplifies.symbols b/tsc/testdata/baselines/reference/conformance/negatedDiscriminantIntersectionSimplifies.symbols new file mode 100644 index 0000000000000..9953292e64b0a --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedDiscriminantIntersectionSimplifies.symbols @@ -0,0 +1,189 @@ +//// [tests/cases/conformance/types/negated/negatedDiscriminantIntersectionSimplifies.ts] //// + +=== negatedDiscriminantIntersectionSimplifies.ts === +// When an intersection 'C & not A' has non-negated part 'C' that is mutually exclusive with the +// negated base 'A' by virtue of a shared discriminant property (a property present on both whose +// literal types are disjoint), the 'not A' member is redundant and is dropped, leaving 'C'. + +interface A { +>A : Symbol(A, Decl(negatedDiscriminantIntersectionSimplifies.ts, 0, 0)) + + kind: "a"; +>kind : Symbol(A.kind, Decl(negatedDiscriminantIntersectionSimplifies.ts, 4, 13)) + + field: string; +>field : Symbol(A.field, Decl(negatedDiscriminantIntersectionSimplifies.ts, 5, 14)) +} +interface B { +>B : Symbol(B, Decl(negatedDiscriminantIntersectionSimplifies.ts, 7, 1)) + + kind: "b"; +>kind : Symbol(B.kind, Decl(negatedDiscriminantIntersectionSimplifies.ts, 8, 13)) + + field: number; +>field : Symbol(B.field, Decl(negatedDiscriminantIntersectionSimplifies.ts, 9, 14)) +} +interface C { +>C : Symbol(C, Decl(negatedDiscriminantIntersectionSimplifies.ts, 11, 1)) + + kind: "c"; +>kind : Symbol(C.kind, Decl(negatedDiscriminantIntersectionSimplifies.ts, 12, 13)) + + field: object; +>field : Symbol(C.field, Decl(negatedDiscriminantIntersectionSimplifies.ts, 13, 14)) +} + +declare function wantsC(x: C): void; +>wantsC : Symbol(wantsC, Decl(negatedDiscriminantIntersectionSimplifies.ts, 15, 1)) +>x : Symbol(x, Decl(negatedDiscriminantIntersectionSimplifies.ts, 17, 24)) +>C : Symbol(C, Decl(negatedDiscriminantIntersectionSimplifies.ts, 11, 1)) + +// 'C & not A' -> 'C' because C.kind ("c") is disjoint from A.kind ("a"). +declare const c1: C & not A; +>c1 : Symbol(c1, Decl(negatedDiscriminantIntersectionSimplifies.ts, 20, 13)) +>C : Symbol(C, Decl(negatedDiscriminantIntersectionSimplifies.ts, 11, 1)) +>A : Symbol(A, Decl(negatedDiscriminantIntersectionSimplifies.ts, 0, 0)) + +c1; // C +>c1 : Symbol(c1, Decl(negatedDiscriminantIntersectionSimplifies.ts, 20, 13)) + +wantsC(c1); +>wantsC : Symbol(wantsC, Decl(negatedDiscriminantIntersectionSimplifies.ts, 15, 1)) +>c1 : Symbol(c1, Decl(negatedDiscriminantIntersectionSimplifies.ts, 20, 13)) + +// Multiple negations, each mutually exclusive with C: 'C & not A & not B' -> 'C'. +declare const c2: C & not A & not B; +>c2 : Symbol(c2, Decl(negatedDiscriminantIntersectionSimplifies.ts, 25, 13)) +>C : Symbol(C, Decl(negatedDiscriminantIntersectionSimplifies.ts, 11, 1)) +>A : Symbol(A, Decl(negatedDiscriminantIntersectionSimplifies.ts, 0, 0)) +>B : Symbol(B, Decl(negatedDiscriminantIntersectionSimplifies.ts, 7, 1)) + +c2; // C +>c2 : Symbol(c2, Decl(negatedDiscriminantIntersectionSimplifies.ts, 25, 13)) + +wantsC(c2); +>wantsC : Symbol(wantsC, Decl(negatedDiscriminantIntersectionSimplifies.ts, 15, 1)) +>c2 : Symbol(c2, Decl(negatedDiscriminantIntersectionSimplifies.ts, 25, 13)) + +// Non-discriminant negation is retained: 'C & not { other: number }' shares no disjoint discriminant. +declare const c3: C & not { other: number }; +>c3 : Symbol(c3, Decl(negatedDiscriminantIntersectionSimplifies.ts, 30, 13)) +>C : Symbol(C, Decl(negatedDiscriminantIntersectionSimplifies.ts, 11, 1)) +>other : Symbol(other, Decl(negatedDiscriminantIntersectionSimplifies.ts, 30, 27)) + +c3; // C & not { other: number; } +>c3 : Symbol(c3, Decl(negatedDiscriminantIntersectionSimplifies.ts, 30, 13)) + +// A negation whose shared property has the SAME discriminant value is retained (not disjoint): +// C.kind and the negated base's kind are both "c", so they are not mutually exclusive. +declare const c4: C & not { kind: "c"; other: number }; +>c4 : Symbol(c4, Decl(negatedDiscriminantIntersectionSimplifies.ts, 35, 13)) +>C : Symbol(C, Decl(negatedDiscriminantIntersectionSimplifies.ts, 11, 1)) +>kind : Symbol(kind, Decl(negatedDiscriminantIntersectionSimplifies.ts, 35, 27)) +>other : Symbol(other, Decl(negatedDiscriminantIntersectionSimplifies.ts, 35, 38)) + +c4; // C & not { kind: "c"; other: number; } +>c4 : Symbol(c4, Decl(negatedDiscriminantIntersectionSimplifies.ts, 35, 13)) + +// Enum discriminants: two distinct string-enum members are mutually exclusive. +enum E { +>E : Symbol(E, Decl(negatedDiscriminantIntersectionSimplifies.ts, 36, 3)) + + A = "a", +>A : Symbol(E.A, Decl(negatedDiscriminantIntersectionSimplifies.ts, 39, 8)) + + B = "b", +>B : Symbol(E.B, Decl(negatedDiscriminantIntersectionSimplifies.ts, 40, 12)) +} +interface EA { +>EA : Symbol(EA, Decl(negatedDiscriminantIntersectionSimplifies.ts, 42, 1)) + + tag: E.A; +>tag : Symbol(EA.tag, Decl(negatedDiscriminantIntersectionSimplifies.ts, 43, 14)) +>E : Symbol(E, Decl(negatedDiscriminantIntersectionSimplifies.ts, 36, 3)) +>A : Symbol(E.A, Decl(negatedDiscriminantIntersectionSimplifies.ts, 39, 8)) + + payload: string; +>payload : Symbol(EA.payload, Decl(negatedDiscriminantIntersectionSimplifies.ts, 44, 13)) +} +interface EB { +>EB : Symbol(EB, Decl(negatedDiscriminantIntersectionSimplifies.ts, 46, 1)) + + tag: E.B; +>tag : Symbol(EB.tag, Decl(negatedDiscriminantIntersectionSimplifies.ts, 47, 14)) +>E : Symbol(E, Decl(negatedDiscriminantIntersectionSimplifies.ts, 36, 3)) +>B : Symbol(E.B, Decl(negatedDiscriminantIntersectionSimplifies.ts, 40, 12)) + + payload: number; +>payload : Symbol(EB.payload, Decl(negatedDiscriminantIntersectionSimplifies.ts, 48, 13)) +} +declare function wantsEA(x: EA): void; +>wantsEA : Symbol(wantsEA, Decl(negatedDiscriminantIntersectionSimplifies.ts, 50, 1)) +>x : Symbol(x, Decl(negatedDiscriminantIntersectionSimplifies.ts, 51, 25)) +>EA : Symbol(EA, Decl(negatedDiscriminantIntersectionSimplifies.ts, 42, 1)) + +// 'EA & not EB' -> 'EA' because E.A and E.B are disjoint enum members. +declare const e1: EA & not EB; +>e1 : Symbol(e1, Decl(negatedDiscriminantIntersectionSimplifies.ts, 54, 13)) +>EA : Symbol(EA, Decl(negatedDiscriminantIntersectionSimplifies.ts, 42, 1)) +>EB : Symbol(EB, Decl(negatedDiscriminantIntersectionSimplifies.ts, 46, 1)) + +e1; // EA +>e1 : Symbol(e1, Decl(negatedDiscriminantIntersectionSimplifies.ts, 54, 13)) + +wantsEA(e1); +>wantsEA : Symbol(wantsEA, Decl(negatedDiscriminantIntersectionSimplifies.ts, 50, 1)) +>e1 : Symbol(e1, Decl(negatedDiscriminantIntersectionSimplifies.ts, 54, 13)) + +// A string-enum member is a *distinct* type from the bare string literal of its value: 'E.A' and +// '"a"' have an empty intersection ('E.A & "a"' is never), so they are mutually exclusive and the +// negation is dropped. This is precisely the case a by-identity comparison of the property types +// would get wrong -- the regular literal type of 'E.A' is the same '"a"', so identity would treat +// them as overlapping and wrongly keep the negation. The intersection-based check gets it right. +declare const e2: EA & not { tag: "a"; payload: number }; +>e2 : Symbol(e2, Decl(negatedDiscriminantIntersectionSimplifies.ts, 63, 13)) +>EA : Symbol(EA, Decl(negatedDiscriminantIntersectionSimplifies.ts, 42, 1)) +>tag : Symbol(tag, Decl(negatedDiscriminantIntersectionSimplifies.ts, 63, 28)) +>payload : Symbol(payload, Decl(negatedDiscriminantIntersectionSimplifies.ts, 63, 38)) + +e2; // EA +>e2 : Symbol(e2, Decl(negatedDiscriminantIntersectionSimplifies.ts, 63, 13)) + +wantsEA(e2); +>wantsEA : Symbol(wantsEA, Decl(negatedDiscriminantIntersectionSimplifies.ts, 50, 1)) +>e2 : Symbol(e2, Decl(negatedDiscriminantIntersectionSimplifies.ts, 63, 13)) + +// The same enum member on both sides is NOT disjoint, so the negation is retained. +declare const e3: EA & not { tag: E.A; extra: number }; +>e3 : Symbol(e3, Decl(negatedDiscriminantIntersectionSimplifies.ts, 68, 13)) +>EA : Symbol(EA, Decl(negatedDiscriminantIntersectionSimplifies.ts, 42, 1)) +>tag : Symbol(tag, Decl(negatedDiscriminantIntersectionSimplifies.ts, 68, 28)) +>E : Symbol(E, Decl(negatedDiscriminantIntersectionSimplifies.ts, 36, 3)) +>A : Symbol(E.A, Decl(negatedDiscriminantIntersectionSimplifies.ts, 39, 8)) +>extra : Symbol(extra, Decl(negatedDiscriminantIntersectionSimplifies.ts, 68, 38)) + +e3; // EA & not { tag: E.A; extra: number; } +>e3 : Symbol(e3, Decl(negatedDiscriminantIntersectionSimplifies.ts, 68, 13)) + +// A union-of-literals discriminant: '"a" | "b"' is disjoint from '"c" | "d"', so the negation is +// dropped even though neither side is a single unit type (a by-identity check would miss this). +interface P { +>P : Symbol(P, Decl(negatedDiscriminantIntersectionSimplifies.ts, 69, 3)) + + kind: "a" | "b"; +>kind : Symbol(P.kind, Decl(negatedDiscriminantIntersectionSimplifies.ts, 73, 13)) + + p: string; +>p : Symbol(P.p, Decl(negatedDiscriminantIntersectionSimplifies.ts, 74, 20)) +} +declare const u1: P & not { kind: "c" | "d"; p: number }; +>u1 : Symbol(u1, Decl(negatedDiscriminantIntersectionSimplifies.ts, 77, 13)) +>P : Symbol(P, Decl(negatedDiscriminantIntersectionSimplifies.ts, 69, 3)) +>kind : Symbol(kind, Decl(negatedDiscriminantIntersectionSimplifies.ts, 77, 27)) +>p : Symbol(p, Decl(negatedDiscriminantIntersectionSimplifies.ts, 77, 44)) + +u1; // P +>u1 : Symbol(u1, Decl(negatedDiscriminantIntersectionSimplifies.ts, 77, 13)) + + + diff --git a/tsc/testdata/baselines/reference/conformance/negatedDiscriminantIntersectionSimplifies.types b/tsc/testdata/baselines/reference/conformance/negatedDiscriminantIntersectionSimplifies.types new file mode 100644 index 0000000000000..8cb6863c912af --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedDiscriminantIntersectionSimplifies.types @@ -0,0 +1,166 @@ +//// [tests/cases/conformance/types/negated/negatedDiscriminantIntersectionSimplifies.ts] //// + +=== negatedDiscriminantIntersectionSimplifies.ts === +// When an intersection 'C & not A' has non-negated part 'C' that is mutually exclusive with the +// negated base 'A' by virtue of a shared discriminant property (a property present on both whose +// literal types are disjoint), the 'not A' member is redundant and is dropped, leaving 'C'. + +interface A { + kind: "a"; +>kind : "a" + + field: string; +>field : string +} +interface B { + kind: "b"; +>kind : "b" + + field: number; +>field : number +} +interface C { + kind: "c"; +>kind : "c" + + field: object; +>field : object +} + +declare function wantsC(x: C): void; +>wantsC : (x: C) => void +>x : C + +// 'C & not A' -> 'C' because C.kind ("c") is disjoint from A.kind ("a"). +declare const c1: C & not A; +>c1 : C + +c1; // C +>c1 : C + +wantsC(c1); +>wantsC(c1) : void +>wantsC : (x: C) => void +>c1 : C + +// Multiple negations, each mutually exclusive with C: 'C & not A & not B' -> 'C'. +declare const c2: C & not A & not B; +>c2 : C + +c2; // C +>c2 : C + +wantsC(c2); +>wantsC(c2) : void +>wantsC : (x: C) => void +>c2 : C + +// Non-discriminant negation is retained: 'C & not { other: number }' shares no disjoint discriminant. +declare const c3: C & not { other: number }; +>c3 : C & not { other: number; } +>other : number + +c3; // C & not { other: number; } +>c3 : C & not { other: number; } + +// A negation whose shared property has the SAME discriminant value is retained (not disjoint): +// C.kind and the negated base's kind are both "c", so they are not mutually exclusive. +declare const c4: C & not { kind: "c"; other: number }; +>c4 : C & not { kind: "c"; other: number; } +>kind : "c" +>other : number + +c4; // C & not { kind: "c"; other: number; } +>c4 : C & not { kind: "c"; other: number; } + +// Enum discriminants: two distinct string-enum members are mutually exclusive. +enum E { +>E : E + + A = "a", +>A : E.A +>"a" : "a" + + B = "b", +>B : E.B +>"b" : "b" +} +interface EA { + tag: E.A; +>tag : E.A +>E : any + + payload: string; +>payload : string +} +interface EB { + tag: E.B; +>tag : E.B +>E : any + + payload: number; +>payload : number +} +declare function wantsEA(x: EA): void; +>wantsEA : (x: EA) => void +>x : EA + +// 'EA & not EB' -> 'EA' because E.A and E.B are disjoint enum members. +declare const e1: EA & not EB; +>e1 : EA + +e1; // EA +>e1 : EA + +wantsEA(e1); +>wantsEA(e1) : void +>wantsEA : (x: EA) => void +>e1 : EA + +// A string-enum member is a *distinct* type from the bare string literal of its value: 'E.A' and +// '"a"' have an empty intersection ('E.A & "a"' is never), so they are mutually exclusive and the +// negation is dropped. This is precisely the case a by-identity comparison of the property types +// would get wrong -- the regular literal type of 'E.A' is the same '"a"', so identity would treat +// them as overlapping and wrongly keep the negation. The intersection-based check gets it right. +declare const e2: EA & not { tag: "a"; payload: number }; +>e2 : EA +>tag : "a" +>payload : number + +e2; // EA +>e2 : EA + +wantsEA(e2); +>wantsEA(e2) : void +>wantsEA : (x: EA) => void +>e2 : EA + +// The same enum member on both sides is NOT disjoint, so the negation is retained. +declare const e3: EA & not { tag: E.A; extra: number }; +>e3 : EA & not { tag: E.A; extra: number; } +>tag : E.A +>E : any +>extra : number + +e3; // EA & not { tag: E.A; extra: number; } +>e3 : EA & not { tag: E.A; extra: number; } + +// A union-of-literals discriminant: '"a" | "b"' is disjoint from '"c" | "d"', so the negation is +// dropped even though neither side is a single unit type (a by-identity check would miss this). +interface P { + kind: "a" | "b"; +>kind : "a" | "b" + + p: string; +>p : string +} +declare const u1: P & not { kind: "c" | "d"; p: number }; +>u1 : P +>kind : "c" | "d" +>p : number + +u1; // P +>u1 : P + + + diff --git a/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.errors.txt new file mode 100644 index 0000000000000..7132e50198dc8 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.errors.txt @@ -0,0 +1,21 @@ +negatedFreshTreatedAsClosedSet.ts(10,4): error TS2345: Argument of type '{ x: number; y: number; }' is not assignable to parameter of type 'Distinct<{ x: any; }, { y: any; }>'. + Type '{ x: number; y: number; }' is not assignable to type '{ y: any; } & not ({ x: any; } & { y: any; })'. + Type '{ x: number; y: number; }' is not assignable to type 'not ({ x: any; } & { y: any; })'. + + +==== negatedFreshTreatedAsClosedSet.ts (1 errors) ==== + // from https://github.com/Microsoft/TypeScript/issues/4183 + type Distinct = (A | B) & not (A & B); + declare var o1: {x: any}; + declare var o2: {y: any}; + + declare function f1(x: Distinct): void; + + f1({x: 0}); // OK + f1({y: 0}); // OK + f1({x: 0, y: 0}); // Should error + ~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ x: number; y: number; }' is not assignable to parameter of type 'Distinct<{ x: any; }, { y: any; }>'. +!!! error TS2345: Type '{ x: number; y: number; }' is not assignable to type '{ y: any; } & not ({ x: any; } & { y: any; })'. +!!! error TS2345: Type '{ x: number; y: number; }' is not assignable to type 'not ({ x: any; } & { y: any; })'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.js b/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.js new file mode 100644 index 0000000000000..7e1e66d0c3d1e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.js @@ -0,0 +1,20 @@ +//// [tests/cases/conformance/types/negated/negatedFreshTreatedAsClosedSet.ts] //// + +//// [negatedFreshTreatedAsClosedSet.ts] +// from https://github.com/Microsoft/TypeScript/issues/4183 +type Distinct = (A | B) & not (A & B); +declare var o1: {x: any}; +declare var o2: {y: any}; + +declare function f1(x: Distinct): void; + +f1({x: 0}); // OK +f1({y: 0}); // OK +f1({x: 0, y: 0}); // Should error + + +//// [negatedFreshTreatedAsClosedSet.js] +"use strict"; +f1({ x: 0 }); // OK +f1({ y: 0 }); // OK +f1({ x: 0, y: 0 }); // Should error diff --git a/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.symbols b/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.symbols new file mode 100644 index 0000000000000..585bbbab5e493 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.symbols @@ -0,0 +1,41 @@ +//// [tests/cases/conformance/types/negated/negatedFreshTreatedAsClosedSet.ts] //// + +=== negatedFreshTreatedAsClosedSet.ts === +// from https://github.com/Microsoft/TypeScript/issues/4183 +type Distinct = (A | B) & not (A & B); +>Distinct : Symbol(Distinct, Decl(negatedFreshTreatedAsClosedSet.ts, 0, 0)) +>A : Symbol(A, Decl(negatedFreshTreatedAsClosedSet.ts, 1, 14)) +>B : Symbol(B, Decl(negatedFreshTreatedAsClosedSet.ts, 1, 16)) +>A : Symbol(A, Decl(negatedFreshTreatedAsClosedSet.ts, 1, 14)) +>B : Symbol(B, Decl(negatedFreshTreatedAsClosedSet.ts, 1, 16)) +>A : Symbol(A, Decl(negatedFreshTreatedAsClosedSet.ts, 1, 14)) +>B : Symbol(B, Decl(negatedFreshTreatedAsClosedSet.ts, 1, 16)) + +declare var o1: {x: any}; +>o1 : Symbol(o1, Decl(negatedFreshTreatedAsClosedSet.ts, 2, 11)) +>x : Symbol(x, Decl(negatedFreshTreatedAsClosedSet.ts, 2, 17)) + +declare var o2: {y: any}; +>o2 : Symbol(o2, Decl(negatedFreshTreatedAsClosedSet.ts, 3, 11)) +>y : Symbol(y, Decl(negatedFreshTreatedAsClosedSet.ts, 3, 17)) + +declare function f1(x: Distinct): void; +>f1 : Symbol(f1, Decl(negatedFreshTreatedAsClosedSet.ts, 3, 25)) +>x : Symbol(x, Decl(negatedFreshTreatedAsClosedSet.ts, 5, 20)) +>Distinct : Symbol(Distinct, Decl(negatedFreshTreatedAsClosedSet.ts, 0, 0)) +>o1 : Symbol(o1, Decl(negatedFreshTreatedAsClosedSet.ts, 2, 11)) +>o2 : Symbol(o2, Decl(negatedFreshTreatedAsClosedSet.ts, 3, 11)) + +f1({x: 0}); // OK +>f1 : Symbol(f1, Decl(negatedFreshTreatedAsClosedSet.ts, 3, 25)) +>x : Symbol(x, Decl(negatedFreshTreatedAsClosedSet.ts, 7, 4)) + +f1({y: 0}); // OK +>f1 : Symbol(f1, Decl(negatedFreshTreatedAsClosedSet.ts, 3, 25)) +>y : Symbol(y, Decl(negatedFreshTreatedAsClosedSet.ts, 8, 4)) + +f1({x: 0, y: 0}); // Should error +>f1 : Symbol(f1, Decl(negatedFreshTreatedAsClosedSet.ts, 3, 25)) +>x : Symbol(x, Decl(negatedFreshTreatedAsClosedSet.ts, 9, 4)) +>y : Symbol(y, Decl(negatedFreshTreatedAsClosedSet.ts, 9, 9)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.types b/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.types new file mode 100644 index 0000000000000..72dd2bf45ccc9 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedFreshTreatedAsClosedSet.types @@ -0,0 +1,44 @@ +//// [tests/cases/conformance/types/negated/negatedFreshTreatedAsClosedSet.ts] //// + +=== negatedFreshTreatedAsClosedSet.ts === +// from https://github.com/Microsoft/TypeScript/issues/4183 +type Distinct = (A | B) & not (A & B); +>Distinct : Distinct + +declare var o1: {x: any}; +>o1 : { x: any; } +>x : any + +declare var o2: {y: any}; +>o2 : { y: any; } +>y : any + +declare function f1(x: Distinct): void; +>f1 : (x: Distinct) => void +>x : Distinct<{ x: any; }, { y: any; }> +>o1 : { x: any; } +>o2 : { y: any; } + +f1({x: 0}); // OK +>f1({x: 0}) : void +>f1 : (x: Distinct) => void +>{x: 0} : { x: number; } +>x : number +>0 : 0 + +f1({y: 0}); // OK +>f1({y: 0}) : void +>f1 : (x: Distinct) => void +>{y: 0} : { y: number; } +>y : number +>0 : 0 + +f1({x: 0, y: 0}); // Should error +>f1({x: 0, y: 0}) : void +>f1 : (x: Distinct) => void +>{x: 0, y: 0} : { x: number; y: number; } +>x : number +>0 : 0 +>y : number +>0 : 0 + diff --git a/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.errors.txt new file mode 100644 index 0000000000000..d6b7cb6448763 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.errors.txt @@ -0,0 +1,30 @@ +negatedInMappedTypeDisablesExcessProperties.ts(22,5): error TS2322: Type 'number' is not assignable to type 'string'. + + +==== negatedInMappedTypeDisablesExcessProperties.ts (1 errors) ==== + // https://github.com/Microsoft/TypeScript/issues/4196 + // needs https://github.com/Microsoft/TypeScript/pull/26797 to work, as even though the mapped type can be + // written, the key type `string & ~("foo" | "bar")` can't be represented as properties or string/number index + // signatures + + type Config = { + foo: number; + bar: number; + } & { + [k in (string & not ("foo" | "bar"))]: string; + }; + + const conf: Config = { + foo: 12, + bar: 12, + other: "string" + }; // OK + + const conf2: Config = { + foo: 12, + bar: 12, + other: 0, + ~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }; // Should error + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.js b/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.js new file mode 100644 index 0000000000000..06e573b2caf1a --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.js @@ -0,0 +1,44 @@ +//// [tests/cases/conformance/types/negated/negatedInMappedTypeDisablesExcessProperties.ts] //// + +//// [negatedInMappedTypeDisablesExcessProperties.ts] +// https://github.com/Microsoft/TypeScript/issues/4196 +// needs https://github.com/Microsoft/TypeScript/pull/26797 to work, as even though the mapped type can be +// written, the key type `string & ~("foo" | "bar")` can't be represented as properties or string/number index +// signatures + +type Config = { + foo: number; + bar: number; +} & { + [k in (string & not ("foo" | "bar"))]: string; +}; + +const conf: Config = { + foo: 12, + bar: 12, + other: "string" +}; // OK + +const conf2: Config = { + foo: 12, + bar: 12, + other: 0, +}; // Should error + + +//// [negatedInMappedTypeDisablesExcessProperties.js] +"use strict"; +// https://github.com/Microsoft/TypeScript/issues/4196 +// needs https://github.com/Microsoft/TypeScript/pull/26797 to work, as even though the mapped type can be +// written, the key type `string & ~("foo" | "bar")` can't be represented as properties or string/number index +// signatures +const conf = { + foo: 12, + bar: 12, + other: "string" +}; // OK +const conf2 = { + foo: 12, + bar: 12, + other: 0, +}; // Should error diff --git a/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.symbols b/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.symbols new file mode 100644 index 0000000000000..100a3bb46360b --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.symbols @@ -0,0 +1,53 @@ +//// [tests/cases/conformance/types/negated/negatedInMappedTypeDisablesExcessProperties.ts] //// + +=== negatedInMappedTypeDisablesExcessProperties.ts === +// https://github.com/Microsoft/TypeScript/issues/4196 +// needs https://github.com/Microsoft/TypeScript/pull/26797 to work, as even though the mapped type can be +// written, the key type `string & ~("foo" | "bar")` can't be represented as properties or string/number index +// signatures + +type Config = { +>Config : Symbol(Config, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 0, 0)) + + foo: number; +>foo : Symbol(foo, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 5, 15)) + + bar: number; +>bar : Symbol(bar, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 6, 16)) + +} & { + [k in (string & not ("foo" | "bar"))]: string; +>k : Symbol(k, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 9, 5)) + +}; + +const conf: Config = { +>conf : Symbol(conf, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 12, 5)) +>Config : Symbol(Config, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 0, 0)) + + foo: 12, +>foo : Symbol(foo, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 12, 22)) + + bar: 12, +>bar : Symbol(bar, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 13, 12)) + + other: "string" +>other : Symbol(other, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 14, 12)) + +}; // OK + +const conf2: Config = { +>conf2 : Symbol(conf2, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 18, 5)) +>Config : Symbol(Config, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 0, 0)) + + foo: 12, +>foo : Symbol(foo, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 18, 23)) + + bar: 12, +>bar : Symbol(bar, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 19, 12)) + + other: 0, +>other : Symbol(other, Decl(negatedInMappedTypeDisablesExcessProperties.ts, 20, 12)) + +}; // Should error + diff --git a/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.types b/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.types new file mode 100644 index 0000000000000..f08bc85c8e5ec --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedInMappedTypeDisablesExcessProperties.types @@ -0,0 +1,57 @@ +//// [tests/cases/conformance/types/negated/negatedInMappedTypeDisablesExcessProperties.ts] //// + +=== negatedInMappedTypeDisablesExcessProperties.ts === +// https://github.com/Microsoft/TypeScript/issues/4196 +// needs https://github.com/Microsoft/TypeScript/pull/26797 to work, as even though the mapped type can be +// written, the key type `string & ~("foo" | "bar")` can't be represented as properties or string/number index +// signatures + +type Config = { +>Config : Config + + foo: number; +>foo : number + + bar: number; +>bar : number + +} & { + [k in (string & not ("foo" | "bar"))]: string; +}; + +const conf: Config = { +>conf : Config +>{ foo: 12, bar: 12, other: "string"} : { foo: number; bar: number; other: string; } + + foo: 12, +>foo : number +>12 : 12 + + bar: 12, +>bar : number +>12 : 12 + + other: "string" +>other : string +>"string" : "string" + +}; // OK + +const conf2: Config = { +>conf2 : Config +>{ foo: 12, bar: 12, other: 0,} : { foo: number; bar: number; other: number; } + + foo: 12, +>foo : number +>12 : 12 + + bar: 12, +>bar : number +>12 : 12 + + other: 0, +>other : number +>0 : 0 + +}; // Should error + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingAssertion.symbols b/tsc/testdata/baselines/reference/conformance/negatedNarrowingAssertion.symbols new file mode 100644 index 0000000000000..774f7da15869e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingAssertion.symbols @@ -0,0 +1,93 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingAssertion.ts] //// + +=== negatedNarrowingAssertion.ts === +// Assertion signatures narrow only the (single) continuation after the call. Because there is no +// `false` branch, no fresh CFA negation is introduced; a negation only appears when the assertion +// predicate itself is written with `not`. + +interface Cat { +>Cat : Symbol(Cat, Decl(negatedNarrowingAssertion.ts, 0, 0)) + + meow(): void; +>meow : Symbol(Cat.meow, Decl(negatedNarrowingAssertion.ts, 4, 15)) +} + +declare function assertCat(x: unknown): asserts x is Cat; +>assertCat : Symbol(assertCat, Decl(negatedNarrowingAssertion.ts, 6, 1)) +>x : Symbol(x, Decl(negatedNarrowingAssertion.ts, 8, 27)) +>x : Symbol(x, Decl(negatedNarrowingAssertion.ts, 8, 27)) +>Cat : Symbol(Cat, Decl(negatedNarrowingAssertion.ts, 0, 0)) + +declare function assertNotCat(x: unknown): asserts x is not Cat; +>assertNotCat : Symbol(assertNotCat, Decl(negatedNarrowingAssertion.ts, 8, 57)) +>x : Symbol(x, Decl(negatedNarrowingAssertion.ts, 9, 30)) +>x : Symbol(x, Decl(negatedNarrowingAssertion.ts, 9, 30)) +>Cat : Symbol(Cat, Decl(negatedNarrowingAssertion.ts, 0, 0)) + +declare function assertDefined(x: T): asserts x is NonNullable; +>assertDefined : Symbol(assertDefined, Decl(negatedNarrowingAssertion.ts, 9, 64)) +>T : Symbol(T, Decl(negatedNarrowingAssertion.ts, 10, 31)) +>x : Symbol(x, Decl(negatedNarrowingAssertion.ts, 10, 34)) +>T : Symbol(T, Decl(negatedNarrowingAssertion.ts, 10, 31)) +>x : Symbol(x, Decl(negatedNarrowingAssertion.ts, 10, 34)) +>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(negatedNarrowingAssertion.ts, 10, 31)) + +declare function assertTruthy(x: unknown): asserts x; +>assertTruthy : Symbol(assertTruthy, Decl(negatedNarrowingAssertion.ts, 10, 69)) +>x : Symbol(x, Decl(negatedNarrowingAssertion.ts, 11, 30)) +>x : Symbol(x, Decl(negatedNarrowingAssertion.ts, 11, 30)) + +declare function wantsNotCat(x: not Cat): void; +>wantsNotCat : Symbol(wantsNotCat, Decl(negatedNarrowingAssertion.ts, 11, 53)) +>x : Symbol(x, Decl(negatedNarrowingAssertion.ts, 13, 29)) +>Cat : Symbol(Cat, Decl(negatedNarrowingAssertion.ts, 0, 0)) + +// `asserts x is Cat` narrows to Cat. +declare const a: {}; +>a : Symbol(a, Decl(negatedNarrowingAssertion.ts, 16, 13)) + +assertCat(a); +>assertCat : Symbol(assertCat, Decl(negatedNarrowingAssertion.ts, 6, 1)) +>a : Symbol(a, Decl(negatedNarrowingAssertion.ts, 16, 13)) + +a; // {} & Cat +>a : Symbol(a, Decl(negatedNarrowingAssertion.ts, 16, 13)) + +// `asserts x is not Cat` narrows to `not Cat` (the negation comes from the annotation). +declare const b: {}; +>b : Symbol(b, Decl(negatedNarrowingAssertion.ts, 21, 13)) + +assertNotCat(b); +>assertNotCat : Symbol(assertNotCat, Decl(negatedNarrowingAssertion.ts, 8, 57)) +>b : Symbol(b, Decl(negatedNarrowingAssertion.ts, 21, 13)) + +b; // {} & not Cat +>b : Symbol(b, Decl(negatedNarrowingAssertion.ts, 21, 13)) + +wantsNotCat(b); +>wantsNotCat : Symbol(wantsNotCat, Decl(negatedNarrowingAssertion.ts, 11, 53)) +>b : Symbol(b, Decl(negatedNarrowingAssertion.ts, 21, 13)) + +// `asserts x is NonNullable` removes null/undefined without introducing a negation. +declare const c: string | undefined; +>c : Symbol(c, Decl(negatedNarrowingAssertion.ts, 27, 13)) + +assertDefined(c); +>assertDefined : Symbol(assertDefined, Decl(negatedNarrowingAssertion.ts, 9, 64)) +>c : Symbol(c, Decl(negatedNarrowingAssertion.ts, 27, 13)) + +c; // string +>c : Symbol(c, Decl(negatedNarrowingAssertion.ts, 27, 13)) + +// `asserts x` (truthiness assertion) removes falsy constituents, no negation. +declare const d: {} | undefined | 0; +>d : Symbol(d, Decl(negatedNarrowingAssertion.ts, 32, 13)) + +assertTruthy(d); +>assertTruthy : Symbol(assertTruthy, Decl(negatedNarrowingAssertion.ts, 10, 69)) +>d : Symbol(d, Decl(negatedNarrowingAssertion.ts, 32, 13)) + +d; // {} +>d : Symbol(d, Decl(negatedNarrowingAssertion.ts, 32, 13)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingAssertion.types b/tsc/testdata/baselines/reference/conformance/negatedNarrowingAssertion.types new file mode 100644 index 0000000000000..5cb5c60bac884 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingAssertion.types @@ -0,0 +1,85 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingAssertion.ts] //// + +=== negatedNarrowingAssertion.ts === +// Assertion signatures narrow only the (single) continuation after the call. Because there is no +// `false` branch, no fresh CFA negation is introduced; a negation only appears when the assertion +// predicate itself is written with `not`. + +interface Cat { + meow(): void; +>meow : () => void +} + +declare function assertCat(x: unknown): asserts x is Cat; +>assertCat : (x: unknown) => asserts x is Cat +>x : unknown + +declare function assertNotCat(x: unknown): asserts x is not Cat; +>assertNotCat : (x: unknown) => asserts x is not Cat +>x : unknown + +declare function assertDefined(x: T): asserts x is NonNullable; +>assertDefined : (x: T) => asserts x is NonNullable +>x : T + +declare function assertTruthy(x: unknown): asserts x; +>assertTruthy : (x: unknown) => asserts x +>x : unknown + +declare function wantsNotCat(x: not Cat): void; +>wantsNotCat : (x: not Cat) => void +>x : not Cat + +// `asserts x is Cat` narrows to Cat. +declare const a: {}; +>a : {} + +assertCat(a); +>assertCat(a) : void +>assertCat : (x: unknown) => asserts x is Cat +>a : {} + +a; // {} & Cat +>a : Cat + +// `asserts x is not Cat` narrows to `not Cat` (the negation comes from the annotation). +declare const b: {}; +>b : {} + +assertNotCat(b); +>assertNotCat(b) : void +>assertNotCat : (x: unknown) => asserts x is not Cat +>b : {} + +b; // {} & not Cat +>b : {} & not Cat + +wantsNotCat(b); +>wantsNotCat(b) : void +>wantsNotCat : (x: not Cat) => void +>b : {} & not Cat + +// `asserts x is NonNullable` removes null/undefined without introducing a negation. +declare const c: string | undefined; +>c : string | undefined + +assertDefined(c); +>assertDefined(c) : void +>assertDefined : (x: T) => asserts x is NonNullable +>c : string | undefined + +c; // string +>c : string + +// `asserts x` (truthiness assertion) removes falsy constituents, no negation. +declare const d: {} | undefined | 0; +>d : 0 | {} | undefined + +assertTruthy(d); +>assertTruthy(d) : void +>assertTruthy : (x: unknown) => asserts x +>d : 0 | {} | undefined + +d; // {} +>d : {} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingEquality.symbols b/tsc/testdata/baselines/reference/conformance/negatedNarrowingEquality.symbols new file mode 100644 index 0000000000000..5a73cd70201bb --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingEquality.symbols @@ -0,0 +1,87 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingEquality.ts] //// + +=== negatedNarrowingEquality.ts === +// Direct equality comparisons (`===`, `!==`, `==`, `!=`) to `undefined`, `null`, and literal values +// narrow via type facts and constituent filtering. They do NOT introduce fresh `not` negations, so +// these baselines act as a guard that negations only come from typeof / instanceof / type guards. + +declare function wantsNotUndef(x: not undefined): void; +>wantsNotUndef : Symbol(wantsNotUndef, Decl(negatedNarrowingEquality.ts, 0, 0)) +>x : Symbol(x, Decl(negatedNarrowingEquality.ts, 4, 31)) + +// `=== undefined` removes undefined; the else branch is just `{}` (no `not undefined`). +declare const a: {} | undefined; +>a : Symbol(a, Decl(negatedNarrowingEquality.ts, 7, 13)) + +if (a === undefined) { +>a : Symbol(a, Decl(negatedNarrowingEquality.ts, 7, 13)) +>undefined : Symbol(undefined) + + a; // undefined +>a : Symbol(a, Decl(negatedNarrowingEquality.ts, 7, 13)) + +} else { + a; // {} +>a : Symbol(a, Decl(negatedNarrowingEquality.ts, 7, 13)) +} + +// `!== null` in strict mode. +declare const b: {} | null; +>b : Symbol(b, Decl(negatedNarrowingEquality.ts, 15, 13)) + +if (b !== null) { +>b : Symbol(b, Decl(negatedNarrowingEquality.ts, 15, 13)) + + b; // {} +>b : Symbol(b, Decl(negatedNarrowingEquality.ts, 15, 13)) + +} else { + b; // null +>b : Symbol(b, Decl(negatedNarrowingEquality.ts, 15, 13)) +} + +// Literal comparison filters the matching constituent; the else branch keeps the rest unchanged. +declare const c: "foo" | "bar" | {}; +>c : Symbol(c, Decl(negatedNarrowingEquality.ts, 23, 13)) + +if (c === "foo") { +>c : Symbol(c, Decl(negatedNarrowingEquality.ts, 23, 13)) + + c; // "foo" +>c : Symbol(c, Decl(negatedNarrowingEquality.ts, 23, 13)) + +} else { + c; // "bar" | {} +>c : Symbol(c, Decl(negatedNarrowingEquality.ts, 23, 13)) +} + +// `== null` (double equals) removes both null and undefined. +declare const d: {} | null | undefined; +>d : Symbol(d, Decl(negatedNarrowingEquality.ts, 31, 13)) + +if (d == null) { +>d : Symbol(d, Decl(negatedNarrowingEquality.ts, 31, 13)) + + d; // null | undefined +>d : Symbol(d, Decl(negatedNarrowingEquality.ts, 31, 13)) + +} else { + d; // {} +>d : Symbol(d, Decl(negatedNarrowingEquality.ts, 31, 13)) +} + +// Numeric literal comparison on a `{}` base leaves `{}` unrefined in the else branch. +declare const e: {}; +>e : Symbol(e, Decl(negatedNarrowingEquality.ts, 39, 13)) + +if (e === 0) { +>e : Symbol(e, Decl(negatedNarrowingEquality.ts, 39, 13)) + + e; // {} (0 is comparable to {}) +>e : Symbol(e, Decl(negatedNarrowingEquality.ts, 39, 13)) + +} else { + e; // {} +>e : Symbol(e, Decl(negatedNarrowingEquality.ts, 39, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingEquality.types b/tsc/testdata/baselines/reference/conformance/negatedNarrowingEquality.types new file mode 100644 index 0000000000000..0945bfa913d06 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingEquality.types @@ -0,0 +1,94 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingEquality.ts] //// + +=== negatedNarrowingEquality.ts === +// Direct equality comparisons (`===`, `!==`, `==`, `!=`) to `undefined`, `null`, and literal values +// narrow via type facts and constituent filtering. They do NOT introduce fresh `not` negations, so +// these baselines act as a guard that negations only come from typeof / instanceof / type guards. + +declare function wantsNotUndef(x: not undefined): void; +>wantsNotUndef : (x: not undefined) => void +>x : not undefined + +// `=== undefined` removes undefined; the else branch is just `{}` (no `not undefined`). +declare const a: {} | undefined; +>a : {} | undefined + +if (a === undefined) { +>a === undefined : boolean +>a : {} | undefined +>undefined : undefined + + a; // undefined +>a : undefined + +} else { + a; // {} +>a : {} +} + +// `!== null` in strict mode. +declare const b: {} | null; +>b : {} | null + +if (b !== null) { +>b !== null : boolean +>b : {} | null + + b; // {} +>b : {} + +} else { + b; // null +>b : null +} + +// Literal comparison filters the matching constituent; the else branch keeps the rest unchanged. +declare const c: "foo" | "bar" | {}; +>c : "bar" | "foo" | {} + +if (c === "foo") { +>c === "foo" : boolean +>c : "bar" | "foo" | {} +>"foo" : "foo" + + c; // "foo" +>c : "foo" + +} else { + c; // "bar" | {} +>c : "bar" | ({} & not "foo") +} + +// `== null` (double equals) removes both null and undefined. +declare const d: {} | null | undefined; +>d : {} | null | undefined + +if (d == null) { +>d == null : boolean +>d : {} | null | undefined + + d; // null | undefined +>d : null | undefined + +} else { + d; // {} +>d : {} +} + +// Numeric literal comparison on a `{}` base leaves `{}` unrefined in the else branch. +declare const e: {}; +>e : {} + +if (e === 0) { +>e === 0 : boolean +>e : {} +>0 : 0 + + e; // {} (0 is comparable to {}) +>e : 0 + +} else { + e; // {} +>e : {} & not 0 +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingEqualityLiteral.symbols b/tsc/testdata/baselines/reference/conformance/negatedNarrowingEqualityLiteral.symbols new file mode 100644 index 0000000000000..11604f3b8fb5b --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingEqualityLiteral.symbols @@ -0,0 +1,106 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingEqualityLiteral.ts] //// + +=== negatedNarrowingEqualityLiteral.ts === +// The false branch of a literal equality comparison introduces a negated type, so a base type that +// overlaps the compared value records the exclusion (e.g. 'number & not 0'). + +declare function wantsNonZero(x: number & not 0): void; +>wantsNonZero : Symbol(wantsNonZero, Decl(negatedNarrowingEqualityLiteral.ts, 0, 0)) +>x : Symbol(x, Decl(negatedNarrowingEqualityLiteral.ts, 3, 30)) + +declare function wantsZero(x: 0): void; +>wantsZero : Symbol(wantsZero, Decl(negatedNarrowingEqualityLiteral.ts, 3, 55)) +>x : Symbol(x, Decl(negatedNarrowingEqualityLiteral.ts, 4, 27)) + +declare const n: number; +>n : Symbol(n, Decl(negatedNarrowingEqualityLiteral.ts, 6, 13)) + +if (n === 0) { +>n : Symbol(n, Decl(negatedNarrowingEqualityLiteral.ts, 6, 13)) + + wantsZero(n); // 0 +>wantsZero : Symbol(wantsZero, Decl(negatedNarrowingEqualityLiteral.ts, 3, 55)) +>n : Symbol(n, Decl(negatedNarrowingEqualityLiteral.ts, 6, 13)) + +} else { + n; // number & not 0 +>n : Symbol(n, Decl(negatedNarrowingEqualityLiteral.ts, 6, 13)) + + wantsNonZero(n); +>wantsNonZero : Symbol(wantsNonZero, Decl(negatedNarrowingEqualityLiteral.ts, 0, 0)) +>n : Symbol(n, Decl(negatedNarrowingEqualityLiteral.ts, 6, 13)) +} + +// `!==` flips the branches. +declare const m: number; +>m : Symbol(m, Decl(negatedNarrowingEqualityLiteral.ts, 15, 13)) + +if (m !== 0) { +>m : Symbol(m, Decl(negatedNarrowingEqualityLiteral.ts, 15, 13)) + + m; // number & not 0 +>m : Symbol(m, Decl(negatedNarrowingEqualityLiteral.ts, 15, 13)) + + wantsNonZero(m); +>wantsNonZero : Symbol(wantsNonZero, Decl(negatedNarrowingEqualityLiteral.ts, 0, 0)) +>m : Symbol(m, Decl(negatedNarrowingEqualityLiteral.ts, 15, 13)) + +} else { + wantsZero(m); // 0 +>wantsZero : Symbol(wantsZero, Decl(negatedNarrowingEqualityLiteral.ts, 3, 55)) +>m : Symbol(m, Decl(negatedNarrowingEqualityLiteral.ts, 15, 13)) +} + +// A disjoint union member: 'not 0' is redundant against non-overlapping constituents. +declare const u: 0 | 1 | 2; +>u : Symbol(u, Decl(negatedNarrowingEqualityLiteral.ts, 24, 13)) + +if (u === 0) { +>u : Symbol(u, Decl(negatedNarrowingEqualityLiteral.ts, 24, 13)) + + u; // 0 +>u : Symbol(u, Decl(negatedNarrowingEqualityLiteral.ts, 24, 13)) + +} else { + u; // 1 | 2 +>u : Symbol(u, Decl(negatedNarrowingEqualityLiteral.ts, 24, 13)) +} + +// A string base is disjoint from the numeric literal, so the negation reduces away. +declare const s: string; +>s : Symbol(s, Decl(negatedNarrowingEqualityLiteral.ts, 32, 13)) + +if ((s as unknown) === 0) { +>s : Symbol(s, Decl(negatedNarrowingEqualityLiteral.ts, 32, 13)) + + s; // string +>s : Symbol(s, Decl(negatedNarrowingEqualityLiteral.ts, 32, 13)) + +} else { + s; // string +>s : Symbol(s, Decl(negatedNarrowingEqualityLiteral.ts, 32, 13)) +} + +// String literal comparison on a broad base. +declare function wantsNotFoo(x: string & not "foo"): void; +>wantsNotFoo : Symbol(wantsNotFoo, Decl(negatedNarrowingEqualityLiteral.ts, 37, 1)) +>x : Symbol(x, Decl(negatedNarrowingEqualityLiteral.ts, 40, 29)) + +declare const str: string; +>str : Symbol(str, Decl(negatedNarrowingEqualityLiteral.ts, 41, 13)) + +if (str === "foo") { +>str : Symbol(str, Decl(negatedNarrowingEqualityLiteral.ts, 41, 13)) + + str; // "foo" +>str : Symbol(str, Decl(negatedNarrowingEqualityLiteral.ts, 41, 13)) + +} else { + str; // string & not "foo" +>str : Symbol(str, Decl(negatedNarrowingEqualityLiteral.ts, 41, 13)) + + wantsNotFoo(str); +>wantsNotFoo : Symbol(wantsNotFoo, Decl(negatedNarrowingEqualityLiteral.ts, 37, 1)) +>str : Symbol(str, Decl(negatedNarrowingEqualityLiteral.ts, 41, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingEqualityLiteral.types b/tsc/testdata/baselines/reference/conformance/negatedNarrowingEqualityLiteral.types new file mode 100644 index 0000000000000..08b52790741c1 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingEqualityLiteral.types @@ -0,0 +1,123 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingEqualityLiteral.ts] //// + +=== negatedNarrowingEqualityLiteral.ts === +// The false branch of a literal equality comparison introduces a negated type, so a base type that +// overlaps the compared value records the exclusion (e.g. 'number & not 0'). + +declare function wantsNonZero(x: number & not 0): void; +>wantsNonZero : (x: number & not 0) => void +>x : number & not 0 + +declare function wantsZero(x: 0): void; +>wantsZero : (x: 0) => void +>x : 0 + +declare const n: number; +>n : number + +if (n === 0) { +>n === 0 : boolean +>n : number +>0 : 0 + + wantsZero(n); // 0 +>wantsZero(n) : void +>wantsZero : (x: 0) => void +>n : 0 + +} else { + n; // number & not 0 +>n : number & not 0 + + wantsNonZero(n); +>wantsNonZero(n) : void +>wantsNonZero : (x: number & not 0) => void +>n : number & not 0 +} + +// `!==` flips the branches. +declare const m: number; +>m : number + +if (m !== 0) { +>m !== 0 : boolean +>m : number +>0 : 0 + + m; // number & not 0 +>m : number & not 0 + + wantsNonZero(m); +>wantsNonZero(m) : void +>wantsNonZero : (x: number & not 0) => void +>m : number & not 0 + +} else { + wantsZero(m); // 0 +>wantsZero(m) : void +>wantsZero : (x: 0) => void +>m : 0 +} + +// A disjoint union member: 'not 0' is redundant against non-overlapping constituents. +declare const u: 0 | 1 | 2; +>u : 0 | 1 | 2 + +if (u === 0) { +>u === 0 : boolean +>u : 0 | 1 | 2 +>0 : 0 + + u; // 0 +>u : 0 + +} else { + u; // 1 | 2 +>u : 1 | 2 +} + +// A string base is disjoint from the numeric literal, so the negation reduces away. +declare const s: string; +>s : string + +if ((s as unknown) === 0) { +>(s as unknown) === 0 : boolean +>(s as unknown) : unknown +>s as unknown : unknown +>s : string +>0 : 0 + + s; // string +>s : string + +} else { + s; // string +>s : string +} + +// String literal comparison on a broad base. +declare function wantsNotFoo(x: string & not "foo"): void; +>wantsNotFoo : (x: string & not "foo") => void +>x : string & not "foo" + +declare const str: string; +>str : string + +if (str === "foo") { +>str === "foo" : boolean +>str : string +>"foo" : "foo" + + str; // "foo" +>str : "foo" + +} else { + str; // string & not "foo" +>str : string & not "foo" + + wantsNotFoo(str); +>wantsNotFoo(str) : void +>wantsNotFoo : (x: string & not "foo") => void +>str : string & not "foo" +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingInOperator.symbols b/tsc/testdata/baselines/reference/conformance/negatedNarrowingInOperator.symbols new file mode 100644 index 0000000000000..2ac649fd33edf --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingInOperator.symbols @@ -0,0 +1,80 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingInOperator.ts] //// + +=== negatedNarrowingInOperator.ts === +// The `in` operator narrows by presence/absence of a property. It uses type facts and constituent +// filtering (not fresh `not` negations), so the else branch keeps the property-absent constituents. + +declare function wantsNotHasA(x: not { a: unknown }): void; +>wantsNotHasA : Symbol(wantsNotHasA, Decl(negatedNarrowingInOperator.ts, 0, 0)) +>x : Symbol(x, Decl(negatedNarrowingInOperator.ts, 3, 30)) +>a : Symbol(a, Decl(negatedNarrowingInOperator.ts, 3, 38)) + +interface WithA { +>WithA : Symbol(WithA, Decl(negatedNarrowingInOperator.ts, 3, 59)) + + a: number; +>a : Symbol(WithA.a, Decl(negatedNarrowingInOperator.ts, 5, 17)) +} +interface WithB { +>WithB : Symbol(WithB, Decl(negatedNarrowingInOperator.ts, 7, 1)) + + b: string; +>b : Symbol(WithB.b, Decl(negatedNarrowingInOperator.ts, 8, 17)) +} + +declare const a: WithA | WithB; +>a : Symbol(a, Decl(negatedNarrowingInOperator.ts, 12, 13)) +>WithA : Symbol(WithA, Decl(negatedNarrowingInOperator.ts, 3, 59)) +>WithB : Symbol(WithB, Decl(negatedNarrowingInOperator.ts, 7, 1)) + +if ("a" in a) { +>a : Symbol(a, Decl(negatedNarrowingInOperator.ts, 12, 13)) + + a; // WithA +>a : Symbol(a, Decl(negatedNarrowingInOperator.ts, 12, 13)) + +} else { + a; // WithB +>a : Symbol(a, Decl(negatedNarrowingInOperator.ts, 12, 13)) +} + +// `in` on a `{}` base does not synthesize a negation; the true branch records the tested member. +declare const b: {}; +>b : Symbol(b, Decl(negatedNarrowingInOperator.ts, 20, 13)) + +if ("a" in b) { +>b : Symbol(b, Decl(negatedNarrowingInOperator.ts, 20, 13)) + + b; // Record<"a", unknown> +>b : Symbol(b, Decl(negatedNarrowingInOperator.ts, 20, 13)) + +} else { + b; // {} +>b : Symbol(b, Decl(negatedNarrowingInOperator.ts, 20, 13)) +} + +// Optional property discrimination. +interface Maybe { +>Maybe : Symbol(Maybe, Decl(negatedNarrowingInOperator.ts, 25, 1)) + + kind: "maybe"; +>kind : Symbol(Maybe.kind, Decl(negatedNarrowingInOperator.ts, 28, 17)) + + payload?: string; +>payload : Symbol(Maybe.payload, Decl(negatedNarrowingInOperator.ts, 29, 18)) +} +declare const c: Maybe; +>c : Symbol(c, Decl(negatedNarrowingInOperator.ts, 32, 13)) +>Maybe : Symbol(Maybe, Decl(negatedNarrowingInOperator.ts, 25, 1)) + +if ("payload" in c) { +>c : Symbol(c, Decl(negatedNarrowingInOperator.ts, 32, 13)) + + c; // Maybe +>c : Symbol(c, Decl(negatedNarrowingInOperator.ts, 32, 13)) + +} else { + c; // Maybe +>c : Symbol(c, Decl(negatedNarrowingInOperator.ts, 32, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingInOperator.types b/tsc/testdata/baselines/reference/conformance/negatedNarrowingInOperator.types new file mode 100644 index 0000000000000..a5606124390bd --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingInOperator.types @@ -0,0 +1,77 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingInOperator.ts] //// + +=== negatedNarrowingInOperator.ts === +// The `in` operator narrows by presence/absence of a property. It uses type facts and constituent +// filtering (not fresh `not` negations), so the else branch keeps the property-absent constituents. + +declare function wantsNotHasA(x: not { a: unknown }): void; +>wantsNotHasA : (x: not { a: unknown; }) => void +>x : not { a: unknown; } +>a : unknown + +interface WithA { + a: number; +>a : number +} +interface WithB { + b: string; +>b : string +} + +declare const a: WithA | WithB; +>a : WithA | WithB + +if ("a" in a) { +>"a" in a : boolean +>"a" : "a" +>a : WithA | WithB + + a; // WithA +>a : WithA + +} else { + a; // WithB +>a : WithB +} + +// `in` on a `{}` base does not synthesize a negation; the true branch records the tested member. +declare const b: {}; +>b : {} + +if ("a" in b) { +>"a" in b : boolean +>"a" : "a" +>b : {} + + b; // Record<"a", unknown> +>b : Record<"a", unknown> + +} else { + b; // {} +>b : {} +} + +// Optional property discrimination. +interface Maybe { + kind: "maybe"; +>kind : "maybe" + + payload?: string; +>payload : string | undefined +} +declare const c: Maybe; +>c : Maybe + +if ("payload" in c) { +>"payload" in c : boolean +>"payload" : "payload" +>c : Maybe + + c; // Maybe +>c : Maybe + +} else { + c; // Maybe +>c : Maybe +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingInstanceof.symbols b/tsc/testdata/baselines/reference/conformance/negatedNarrowingInstanceof.symbols new file mode 100644 index 0000000000000..53210567e3f5e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingInstanceof.symbols @@ -0,0 +1,151 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingInstanceof.ts] //// + +=== negatedNarrowingInstanceof.ts === +// `instanceof` narrowing is nominal (prototype-based), so it deliberately does NOT introduce a +// structural `not C` in the false branch. Class types frequently lack nominal tags and are structural +// subtypes of one another, so a structural negation would unsoundly reduce nominally-distinct +// constituents to `never`. This file guards that instanceof narrows by filtering only. + +class Animal { +>Animal : Symbol(Animal, Decl(negatedNarrowingInstanceof.ts, 0, 0)) + + move(): void {} +>move : Symbol(Animal.move, Decl(negatedNarrowingInstanceof.ts, 5, 14)) +} +class Dog extends Animal { +>Dog : Symbol(Dog, Decl(negatedNarrowingInstanceof.ts, 7, 1)) +>Animal : Symbol(Animal, Decl(negatedNarrowingInstanceof.ts, 0, 0)) + + bark(): void {} +>bark : Symbol(Dog.bark, Decl(negatedNarrowingInstanceof.ts, 8, 26)) +} + +// A broad base is narrowed on the true branch but left intact (no `not Dog`) on the false branch. +declare const a: object; +>a : Symbol(a, Decl(negatedNarrowingInstanceof.ts, 13, 13)) + +if (a instanceof Dog) { +>a : Symbol(a, Decl(negatedNarrowingInstanceof.ts, 13, 13)) +>Dog : Symbol(Dog, Decl(negatedNarrowingInstanceof.ts, 7, 1)) + + a; // Dog +>a : Symbol(a, Decl(negatedNarrowingInstanceof.ts, 13, 13)) + +} else { + a; // object +>a : Symbol(a, Decl(negatedNarrowingInstanceof.ts, 13, 13)) +} + +declare const b: {}; +>b : Symbol(b, Decl(negatedNarrowingInstanceof.ts, 20, 13)) + +if (b instanceof Dog) { +>b : Symbol(b, Decl(negatedNarrowingInstanceof.ts, 20, 13)) +>Dog : Symbol(Dog, Decl(negatedNarrowingInstanceof.ts, 7, 1)) + + b; // Dog +>b : Symbol(b, Decl(negatedNarrowingInstanceof.ts, 20, 13)) + +} else { + b; // {} +>b : Symbol(b, Decl(negatedNarrowingInstanceof.ts, 20, 13)) +} + +// A supertype base keeps the whole supertype (no `not Dog`). +declare const c: Animal; +>c : Symbol(c, Decl(negatedNarrowingInstanceof.ts, 28, 13)) +>Animal : Symbol(Animal, Decl(negatedNarrowingInstanceof.ts, 0, 0)) + +if (c instanceof Dog) { +>c : Symbol(c, Decl(negatedNarrowingInstanceof.ts, 28, 13)) +>Dog : Symbol(Dog, Decl(negatedNarrowingInstanceof.ts, 7, 1)) + + c; // Dog +>c : Symbol(c, Decl(negatedNarrowingInstanceof.ts, 28, 13)) + +} else { + c; // Animal +>c : Symbol(c, Decl(negatedNarrowingInstanceof.ts, 28, 13)) +} + +// A bare type parameter: true branch intersects, false branch is unchanged. +function generic(x: T) { +>generic : Symbol(generic, Decl(negatedNarrowingInstanceof.ts, 33, 1)) +>T : Symbol(T, Decl(negatedNarrowingInstanceof.ts, 36, 17)) +>x : Symbol(x, Decl(negatedNarrowingInstanceof.ts, 36, 20)) +>T : Symbol(T, Decl(negatedNarrowingInstanceof.ts, 36, 17)) + + if (x instanceof Dog) { +>x : Symbol(x, Decl(negatedNarrowingInstanceof.ts, 36, 20)) +>Dog : Symbol(Dog, Decl(negatedNarrowingInstanceof.ts, 7, 1)) + + x; // T & Dog +>x : Symbol(x, Decl(negatedNarrowingInstanceof.ts, 36, 20)) + + } else { + x; // T +>x : Symbol(x, Decl(negatedNarrowingInstanceof.ts, 36, 20)) + } +} + +// Structurally-related but nominally-distinct classes must both survive: `Derived2` structurally +// extends `Derived1`, but a `Derived2` instance is not `instanceof Derived1`, so the else branch +// must keep `Derived2` (it must NOT collapse to `never`). +class Base { +>Base : Symbol(Base, Decl(negatedNarrowingInstanceof.ts, 42, 1)) + + basey = ""; +>basey : Symbol(Base.basey, Decl(negatedNarrowingInstanceof.ts, 47, 12)) +} +class Derived1 extends Base { +>Derived1 : Symbol(Derived1, Decl(negatedNarrowingInstanceof.ts, 49, 1)) +>Base : Symbol(Base, Decl(negatedNarrowingInstanceof.ts, 42, 1)) + + d = ""; +>d : Symbol(Derived1.d, Decl(negatedNarrowingInstanceof.ts, 50, 29)) +} +class Derived2 extends Base { +>Derived2 : Symbol(Derived2, Decl(negatedNarrowingInstanceof.ts, 52, 1)) +>Base : Symbol(Base, Decl(negatedNarrowingInstanceof.ts, 42, 1)) + + d = ""; +>d : Symbol(Derived2.d, Decl(negatedNarrowingInstanceof.ts, 53, 29)) + + other = ""; +>other : Symbol(Derived2.other, Decl(negatedNarrowingInstanceof.ts, 54, 11)) +} +declare const e: Derived1 | Derived2; +>e : Symbol(e, Decl(negatedNarrowingInstanceof.ts, 57, 13)) +>Derived1 : Symbol(Derived1, Decl(negatedNarrowingInstanceof.ts, 49, 1)) +>Derived2 : Symbol(Derived2, Decl(negatedNarrowingInstanceof.ts, 52, 1)) + +if (e instanceof Derived1) { +>e : Symbol(e, Decl(negatedNarrowingInstanceof.ts, 57, 13)) +>Derived1 : Symbol(Derived1, Decl(negatedNarrowingInstanceof.ts, 49, 1)) + + e; // Derived1 +>e : Symbol(e, Decl(negatedNarrowingInstanceof.ts, 57, 13)) + +} else { + e; // Derived2 +>e : Symbol(e, Decl(negatedNarrowingInstanceof.ts, 57, 13)) +} + +// A disjoint object constituent is dropped on the true branch and kept on the false branch. +declare const d: Dog | { kind: "other" }; +>d : Symbol(d, Decl(negatedNarrowingInstanceof.ts, 65, 13)) +>Dog : Symbol(Dog, Decl(negatedNarrowingInstanceof.ts, 7, 1)) +>kind : Symbol(kind, Decl(negatedNarrowingInstanceof.ts, 65, 24)) + +if (d instanceof Dog) { +>d : Symbol(d, Decl(negatedNarrowingInstanceof.ts, 65, 13)) +>Dog : Symbol(Dog, Decl(negatedNarrowingInstanceof.ts, 7, 1)) + + d; // Dog +>d : Symbol(d, Decl(negatedNarrowingInstanceof.ts, 65, 13)) + +} else { + d; // { kind: "other"; } +>d : Symbol(d, Decl(negatedNarrowingInstanceof.ts, 65, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingInstanceof.types b/tsc/testdata/baselines/reference/conformance/negatedNarrowingInstanceof.types new file mode 100644 index 0000000000000..32956cd5af9f2 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingInstanceof.types @@ -0,0 +1,155 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingInstanceof.ts] //// + +=== negatedNarrowingInstanceof.ts === +// `instanceof` narrowing is nominal (prototype-based), so it deliberately does NOT introduce a +// structural `not C` in the false branch. Class types frequently lack nominal tags and are structural +// subtypes of one another, so a structural negation would unsoundly reduce nominally-distinct +// constituents to `never`. This file guards that instanceof narrows by filtering only. + +class Animal { +>Animal : Animal + + move(): void {} +>move : () => void +} +class Dog extends Animal { +>Dog : Dog +>Animal : Animal + + bark(): void {} +>bark : () => void +} + +// A broad base is narrowed on the true branch but left intact (no `not Dog`) on the false branch. +declare const a: object; +>a : object + +if (a instanceof Dog) { +>a instanceof Dog : boolean +>a : object +>Dog : typeof Dog + + a; // Dog +>a : Dog + +} else { + a; // object +>a : object +} + +declare const b: {}; +>b : {} + +if (b instanceof Dog) { +>b instanceof Dog : boolean +>b : {} +>Dog : typeof Dog + + b; // Dog +>b : Dog + +} else { + b; // {} +>b : {} +} + +// A supertype base keeps the whole supertype (no `not Dog`). +declare const c: Animal; +>c : Animal + +if (c instanceof Dog) { +>c instanceof Dog : boolean +>c : Animal +>Dog : typeof Dog + + c; // Dog +>c : Dog + +} else { + c; // Animal +>c : Animal +} + +// A bare type parameter: true branch intersects, false branch is unchanged. +function generic(x: T) { +>generic : (x: T) => void +>x : T + + if (x instanceof Dog) { +>x instanceof Dog : boolean +>x : T +>Dog : typeof Dog + + x; // T & Dog +>x : T & Dog + + } else { + x; // T +>x : T + } +} + +// Structurally-related but nominally-distinct classes must both survive: `Derived2` structurally +// extends `Derived1`, but a `Derived2` instance is not `instanceof Derived1`, so the else branch +// must keep `Derived2` (it must NOT collapse to `never`). +class Base { +>Base : Base + + basey = ""; +>basey : string +>"" : "" +} +class Derived1 extends Base { +>Derived1 : Derived1 +>Base : Base + + d = ""; +>d : string +>"" : "" +} +class Derived2 extends Base { +>Derived2 : Derived2 +>Base : Base + + d = ""; +>d : string +>"" : "" + + other = ""; +>other : string +>"" : "" +} +declare const e: Derived1 | Derived2; +>e : Derived1 | Derived2 + +if (e instanceof Derived1) { +>e instanceof Derived1 : boolean +>e : Derived1 | Derived2 +>Derived1 : typeof Derived1 + + e; // Derived1 +>e : Derived1 + +} else { + e; // Derived2 +>e : Derived2 +} + +// A disjoint object constituent is dropped on the true branch and kept on the false branch. +declare const d: Dog | { kind: "other" }; +>d : Dog | { kind: "other"; } +>kind : "other" + +if (d instanceof Dog) { +>d instanceof Dog : boolean +>d : Dog | { kind: "other"; } +>Dog : typeof Dog + + d; // Dog +>d : Dog + +} else { + d; // { kind: "other"; } +>d : { kind: "other"; } +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTrue.symbols b/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTrue.symbols new file mode 100644 index 0000000000000..c9ea704f08daa --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTrue.symbols @@ -0,0 +1,108 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingSwitchTrue.ts] //// + +=== negatedNarrowingSwitchTrue.ts === +// `switch (true)` narrowing evaluates each case's condition against the reference. Each subsequent +// case sees the negation of the preceding conditions. This exercises the interaction between the +// fresh CFA negations introduced by instanceof/typeof and the switch-on-true clause narrowing. + +class A { +>A : Symbol(A, Decl(negatedNarrowingSwitchTrue.ts, 0, 0)) + + a = 1; +>a : Symbol(A.a, Decl(negatedNarrowingSwitchTrue.ts, 4, 9)) +} +class B { +>B : Symbol(B, Decl(negatedNarrowingSwitchTrue.ts, 6, 1)) + + b = 2; +>b : Symbol(B.b, Decl(negatedNarrowingSwitchTrue.ts, 7, 9)) +} +class C { +>C : Symbol(C, Decl(negatedNarrowingSwitchTrue.ts, 9, 1)) + + c = 3; +>c : Symbol(C.c, Decl(negatedNarrowingSwitchTrue.ts, 10, 9)) +} + +declare const x: A | B | C; +>x : Symbol(x, Decl(negatedNarrowingSwitchTrue.ts, 14, 13)) +>A : Symbol(A, Decl(negatedNarrowingSwitchTrue.ts, 0, 0)) +>B : Symbol(B, Decl(negatedNarrowingSwitchTrue.ts, 6, 1)) +>C : Symbol(C, Decl(negatedNarrowingSwitchTrue.ts, 9, 1)) + +switch (true) { + case x instanceof A: +>x : Symbol(x, Decl(negatedNarrowingSwitchTrue.ts, 14, 13)) +>A : Symbol(A, Decl(negatedNarrowingSwitchTrue.ts, 0, 0)) + + x; // A +>x : Symbol(x, Decl(negatedNarrowingSwitchTrue.ts, 14, 13)) + + break; + case x instanceof B: +>x : Symbol(x, Decl(negatedNarrowingSwitchTrue.ts, 14, 13)) +>B : Symbol(B, Decl(negatedNarrowingSwitchTrue.ts, 6, 1)) + + x; // B +>x : Symbol(x, Decl(negatedNarrowingSwitchTrue.ts, 14, 13)) + + break; + default: + x; // C +>x : Symbol(x, Decl(negatedNarrowingSwitchTrue.ts, 14, 13)) +} + +// typeof-based switch(true). +declare const y: {}; +>y : Symbol(y, Decl(negatedNarrowingSwitchTrue.ts, 27, 13)) + +switch (true) { + case typeof y === "string": +>y : Symbol(y, Decl(negatedNarrowingSwitchTrue.ts, 27, 13)) + + y; // string +>y : Symbol(y, Decl(negatedNarrowingSwitchTrue.ts, 27, 13)) + + break; + case typeof y === "number": +>y : Symbol(y, Decl(negatedNarrowingSwitchTrue.ts, 27, 13)) + + y; // number +>y : Symbol(y, Decl(negatedNarrowingSwitchTrue.ts, 27, 13)) + + break; + default: + y; // {} & not string & not number +>y : Symbol(y, Decl(negatedNarrowingSwitchTrue.ts, 27, 13)) +} + +// A guard-based switch(true). +interface Cat { +>Cat : Symbol(Cat, Decl(negatedNarrowingSwitchTrue.ts, 37, 1)) + + meow(): void; +>meow : Symbol(Cat.meow, Decl(negatedNarrowingSwitchTrue.ts, 40, 15)) +} +declare function isCat(v: unknown): v is Cat; +>isCat : Symbol(isCat, Decl(negatedNarrowingSwitchTrue.ts, 42, 1)) +>v : Symbol(v, Decl(negatedNarrowingSwitchTrue.ts, 43, 23)) +>v : Symbol(v, Decl(negatedNarrowingSwitchTrue.ts, 43, 23)) +>Cat : Symbol(Cat, Decl(negatedNarrowingSwitchTrue.ts, 37, 1)) + +declare const z: {}; +>z : Symbol(z, Decl(negatedNarrowingSwitchTrue.ts, 44, 13)) + +switch (true) { + case isCat(z): +>isCat : Symbol(isCat, Decl(negatedNarrowingSwitchTrue.ts, 42, 1)) +>z : Symbol(z, Decl(negatedNarrowingSwitchTrue.ts, 44, 13)) + + z; // {} & Cat +>z : Symbol(z, Decl(negatedNarrowingSwitchTrue.ts, 44, 13)) + + break; + default: + z; // {} & not Cat +>z : Symbol(z, Decl(negatedNarrowingSwitchTrue.ts, 44, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTrue.types b/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTrue.types new file mode 100644 index 0000000000000..c06bcd5d66dec --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTrue.types @@ -0,0 +1,119 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingSwitchTrue.ts] //// + +=== negatedNarrowingSwitchTrue.ts === +// `switch (true)` narrowing evaluates each case's condition against the reference. Each subsequent +// case sees the negation of the preceding conditions. This exercises the interaction between the +// fresh CFA negations introduced by instanceof/typeof and the switch-on-true clause narrowing. + +class A { +>A : A + + a = 1; +>a : number +>1 : 1 +} +class B { +>B : B + + b = 2; +>b : number +>2 : 2 +} +class C { +>C : C + + c = 3; +>c : number +>3 : 3 +} + +declare const x: A | B | C; +>x : A | B | C + +switch (true) { +>true : true + + case x instanceof A: +>x instanceof A : boolean +>x : A | B | C +>A : typeof A + + x; // A +>x : A + + break; + case x instanceof B: +>x instanceof B : boolean +>x : A | B | C +>B : typeof B + + x; // B +>x : B + + break; + default: + x; // C +>x : C +} + +// typeof-based switch(true). +declare const y: {}; +>y : {} + +switch (true) { +>true : true + + case typeof y === "string": +>typeof y === "string" : boolean +>typeof y : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>y : {} +>"string" : "string" + + y; // string +>y : string + + break; + case typeof y === "number": +>typeof y === "number" : boolean +>typeof y : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>y : {} +>"number" : "number" + + y; // number +>y : number + + break; + default: + y; // {} & not string & not number +>y : {} & not string & not number +} + +// A guard-based switch(true). +interface Cat { + meow(): void; +>meow : () => void +} +declare function isCat(v: unknown): v is Cat; +>isCat : (v: unknown) => v is Cat +>v : unknown + +declare const z: {}; +>z : {} + +switch (true) { +>true : true + + case isCat(z): +>isCat(z) : boolean +>isCat : (v: unknown) => v is Cat +>z : {} + + z; // {} & Cat +>z : Cat + + break; + default: + z; // {} & not Cat +>z : {} & not Cat +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTypeof.symbols b/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTypeof.symbols new file mode 100644 index 0000000000000..05179f0f9d0a6 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTypeof.symbols @@ -0,0 +1,69 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingSwitchTypeof.ts] //// + +=== negatedNarrowingSwitchTypeof.ts === +// `switch (typeof x)` narrowing. Each case narrows to the primitive; the `default` clause is the +// negation of all handled primitives. + +declare function wantsNotStr(x: not string): void; +>wantsNotStr : Symbol(wantsNotStr, Decl(negatedNarrowingSwitchTypeof.ts, 0, 0)) +>x : Symbol(x, Decl(negatedNarrowingSwitchTypeof.ts, 3, 29)) + +declare const a: {}; +>a : Symbol(a, Decl(negatedNarrowingSwitchTypeof.ts, 5, 13)) + +switch (typeof a) { +>a : Symbol(a, Decl(negatedNarrowingSwitchTypeof.ts, 5, 13)) + + case "string": + a; // string +>a : Symbol(a, Decl(negatedNarrowingSwitchTypeof.ts, 5, 13)) + + break; + case "number": + a; // number +>a : Symbol(a, Decl(negatedNarrowingSwitchTypeof.ts, 5, 13)) + + break; + default: + a; // {} & not string & not number (default excludes handled primitives) +>a : Symbol(a, Decl(negatedNarrowingSwitchTypeof.ts, 5, 13)) +} + +// A single handled case: default excludes just that primitive. +declare const b: {}; +>b : Symbol(b, Decl(negatedNarrowingSwitchTypeof.ts, 18, 13)) + +switch (typeof b) { +>b : Symbol(b, Decl(negatedNarrowingSwitchTypeof.ts, 18, 13)) + + case "string": + b; // string +>b : Symbol(b, Decl(negatedNarrowingSwitchTypeof.ts, 18, 13)) + + break; + default: + b; // {} & not string +>b : Symbol(b, Decl(negatedNarrowingSwitchTypeof.ts, 18, 13)) + + wantsNotStr(b); +>wantsNotStr : Symbol(wantsNotStr, Decl(negatedNarrowingSwitchTypeof.ts, 0, 0)) +>b : Symbol(b, Decl(negatedNarrowingSwitchTypeof.ts, 18, 13)) +} + +// Disjoint union: default reduces to the unhandled constituents with no lingering negation. +declare const c: string | number | boolean; +>c : Symbol(c, Decl(negatedNarrowingSwitchTypeof.ts, 29, 13)) + +switch (typeof c) { +>c : Symbol(c, Decl(negatedNarrowingSwitchTypeof.ts, 29, 13)) + + case "string": + c; // string +>c : Symbol(c, Decl(negatedNarrowingSwitchTypeof.ts, 29, 13)) + + break; + default: + c; // number | boolean +>c : Symbol(c, Decl(negatedNarrowingSwitchTypeof.ts, 29, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTypeof.types b/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTypeof.types new file mode 100644 index 0000000000000..895daf4cf6879 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingSwitchTypeof.types @@ -0,0 +1,81 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingSwitchTypeof.ts] //// + +=== negatedNarrowingSwitchTypeof.ts === +// `switch (typeof x)` narrowing. Each case narrows to the primitive; the `default` clause is the +// negation of all handled primitives. + +declare function wantsNotStr(x: not string): void; +>wantsNotStr : (x: not string) => void +>x : not string + +declare const a: {}; +>a : {} + +switch (typeof a) { +>typeof a : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>a : {} + + case "string": +>"string" : "string" + + a; // string +>a : string + + break; + case "number": +>"number" : "number" + + a; // number +>a : number + + break; + default: + a; // {} & not string & not number (default excludes handled primitives) +>a : {} & not string & not number +} + +// A single handled case: default excludes just that primitive. +declare const b: {}; +>b : {} + +switch (typeof b) { +>typeof b : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>b : {} + + case "string": +>"string" : "string" + + b; // string +>b : string + + break; + default: + b; // {} & not string +>b : {} & not string + + wantsNotStr(b); +>wantsNotStr(b) : void +>wantsNotStr : (x: not string) => void +>b : {} & not string +} + +// Disjoint union: default reduces to the unhandled constituents with no lingering negation. +declare const c: string | number | boolean; +>c : string | number | boolean + +switch (typeof c) { +>typeof c : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>c : string | number | boolean + + case "string": +>"string" : "string" + + c; // string +>c : string + + break; + default: + c; // number | boolean +>c : number | boolean +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingTruthiness.symbols b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTruthiness.symbols new file mode 100644 index 0000000000000..7354e419081ad --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTruthiness.symbols @@ -0,0 +1,65 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingTruthiness.ts] //// + +=== negatedNarrowingTruthiness.ts === +// Truthiness narrowing removes falsy constituents (0, "", null, undefined, false, NaN) via type +// facts. It does not introduce fresh `not` negations. + +declare const a: {} | undefined | null; +>a : Symbol(a, Decl(negatedNarrowingTruthiness.ts, 3, 13)) + +if (a) { +>a : Symbol(a, Decl(negatedNarrowingTruthiness.ts, 3, 13)) + + a; // {} +>a : Symbol(a, Decl(negatedNarrowingTruthiness.ts, 3, 13)) + +} else { + a; // undefined | null +>a : Symbol(a, Decl(negatedNarrowingTruthiness.ts, 3, 13)) +} + +declare const b: string | 0 | undefined; +>b : Symbol(b, Decl(negatedNarrowingTruthiness.ts, 10, 13)) + +if (b) { +>b : Symbol(b, Decl(negatedNarrowingTruthiness.ts, 10, 13)) + + b; // string (definitely-falsy 0 and undefined removed; no negation introduced) +>b : Symbol(b, Decl(negatedNarrowingTruthiness.ts, 10, 13)) + +} else { + b; // string | 0 | undefined (no `not` synthesized) +>b : Symbol(b, Decl(negatedNarrowingTruthiness.ts, 10, 13)) +} + +// Truthiness on a bare `{}` leaves it unchanged on both branches: the empty object type includes +// falsy primitives (0, "", false, ...), so it is not reduced to `never` in the else branch. +declare const c: {}; +>c : Symbol(c, Decl(negatedNarrowingTruthiness.ts, 19, 13)) + +if (c) { +>c : Symbol(c, Decl(negatedNarrowingTruthiness.ts, 19, 13)) + + c; // {} +>c : Symbol(c, Decl(negatedNarrowingTruthiness.ts, 19, 13)) + +} else { + c; // {} +>c : Symbol(c, Decl(negatedNarrowingTruthiness.ts, 19, 13)) +} + +// Negation via `!` flips the branches. +declare const d: number | undefined; +>d : Symbol(d, Decl(negatedNarrowingTruthiness.ts, 27, 13)) + +if (!d) { +>d : Symbol(d, Decl(negatedNarrowingTruthiness.ts, 27, 13)) + + d; // 0 | undefined +>d : Symbol(d, Decl(negatedNarrowingTruthiness.ts, 27, 13)) + +} else { + d; // number +>d : Symbol(d, Decl(negatedNarrowingTruthiness.ts, 27, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingTruthiness.types b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTruthiness.types new file mode 100644 index 0000000000000..d78dcde63f6c3 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTruthiness.types @@ -0,0 +1,66 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingTruthiness.ts] //// + +=== negatedNarrowingTruthiness.ts === +// Truthiness narrowing removes falsy constituents (0, "", null, undefined, false, NaN) via type +// facts. It does not introduce fresh `not` negations. + +declare const a: {} | undefined | null; +>a : {} | null | undefined + +if (a) { +>a : {} | null | undefined + + a; // {} +>a : {} + +} else { + a; // undefined | null +>a : {} | null | undefined +} + +declare const b: string | 0 | undefined; +>b : string | 0 | undefined + +if (b) { +>b : string | 0 | undefined + + b; // string (definitely-falsy 0 and undefined removed; no negation introduced) +>b : string + +} else { + b; // string | 0 | undefined (no `not` synthesized) +>b : string | 0 | undefined +} + +// Truthiness on a bare `{}` leaves it unchanged on both branches: the empty object type includes +// falsy primitives (0, "", false, ...), so it is not reduced to `never` in the else branch. +declare const c: {}; +>c : {} + +if (c) { +>c : {} + + c; // {} +>c : {} + +} else { + c; // {} +>c : {} +} + +// Negation via `!` flips the branches. +declare const d: number | undefined; +>d : number | undefined + +if (!d) { +>!d : boolean +>d : number | undefined + + d; // 0 | undefined +>d : number | undefined + +} else { + d; // number +>d : number +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypePredicate.symbols b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypePredicate.symbols new file mode 100644 index 0000000000000..f580a0424271e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypePredicate.symbols @@ -0,0 +1,117 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingTypePredicate.ts] //// + +=== negatedNarrowingTypePredicate.ts === +// Control flow narrowing by a user-defined type guard `x is T`. In the false branch a fresh +// `not T` is intersected in and survives where the base type overlaps T. + +interface Cat { +>Cat : Symbol(Cat, Decl(negatedNarrowingTypePredicate.ts, 0, 0)) + + meow(): void; +>meow : Symbol(Cat.meow, Decl(negatedNarrowingTypePredicate.ts, 3, 15)) +} + +declare function isCat(x: unknown): x is Cat; +>isCat : Symbol(isCat, Decl(negatedNarrowingTypePredicate.ts, 5, 1)) +>x : Symbol(x, Decl(negatedNarrowingTypePredicate.ts, 7, 23)) +>x : Symbol(x, Decl(negatedNarrowingTypePredicate.ts, 7, 23)) +>Cat : Symbol(Cat, Decl(negatedNarrowingTypePredicate.ts, 0, 0)) + +declare function wantsNotCat(x: not Cat): void; +>wantsNotCat : Symbol(wantsNotCat, Decl(negatedNarrowingTypePredicate.ts, 7, 45)) +>x : Symbol(x, Decl(negatedNarrowingTypePredicate.ts, 8, 29)) +>Cat : Symbol(Cat, Decl(negatedNarrowingTypePredicate.ts, 0, 0)) + +// `{}` base overlaps Cat. +declare const a: {}; +>a : Symbol(a, Decl(negatedNarrowingTypePredicate.ts, 11, 13)) + +if (isCat(a)) { +>isCat : Symbol(isCat, Decl(negatedNarrowingTypePredicate.ts, 5, 1)) +>a : Symbol(a, Decl(negatedNarrowingTypePredicate.ts, 11, 13)) + + a; // {} & Cat +>a : Symbol(a, Decl(negatedNarrowingTypePredicate.ts, 11, 13)) + +} else { + a; // {} & not Cat +>a : Symbol(a, Decl(negatedNarrowingTypePredicate.ts, 11, 13)) + + wantsNotCat(a); +>wantsNotCat : Symbol(wantsNotCat, Decl(negatedNarrowingTypePredicate.ts, 7, 45)) +>a : Symbol(a, Decl(negatedNarrowingTypePredicate.ts, 11, 13)) +} + +// A bare type parameter. +function generic(x: T) { +>generic : Symbol(generic, Decl(negatedNarrowingTypePredicate.ts, 17, 1)) +>T : Symbol(T, Decl(negatedNarrowingTypePredicate.ts, 20, 17)) +>x : Symbol(x, Decl(negatedNarrowingTypePredicate.ts, 20, 20)) +>T : Symbol(T, Decl(negatedNarrowingTypePredicate.ts, 20, 17)) + + if (isCat(x)) { +>isCat : Symbol(isCat, Decl(negatedNarrowingTypePredicate.ts, 5, 1)) +>x : Symbol(x, Decl(negatedNarrowingTypePredicate.ts, 20, 20)) + + x; // T & Cat +>x : Symbol(x, Decl(negatedNarrowingTypePredicate.ts, 20, 20)) + + } else { + x; // T & not Cat +>x : Symbol(x, Decl(negatedNarrowingTypePredicate.ts, 20, 20)) + } +} + +// A disjoint union: `not Cat` reduces away against the non-Cat constituent. +interface Dog { +>Dog : Symbol(Dog, Decl(negatedNarrowingTypePredicate.ts, 26, 1)) + + bark(): void; +>bark : Symbol(Dog.bark, Decl(negatedNarrowingTypePredicate.ts, 29, 15)) + + meow?: undefined; +>meow : Symbol(Dog.meow, Decl(negatedNarrowingTypePredicate.ts, 30, 17)) +} +declare const b: Cat | Dog; +>b : Symbol(b, Decl(negatedNarrowingTypePredicate.ts, 33, 13)) +>Cat : Symbol(Cat, Decl(negatedNarrowingTypePredicate.ts, 0, 0)) +>Dog : Symbol(Dog, Decl(negatedNarrowingTypePredicate.ts, 26, 1)) + +if (isCat(b)) { +>isCat : Symbol(isCat, Decl(negatedNarrowingTypePredicate.ts, 5, 1)) +>b : Symbol(b, Decl(negatedNarrowingTypePredicate.ts, 33, 13)) + + b; // Cat +>b : Symbol(b, Decl(negatedNarrowingTypePredicate.ts, 33, 13)) + +} else { + b; // Dog +>b : Symbol(b, Decl(negatedNarrowingTypePredicate.ts, 33, 13)) +} + +// A negated type guard `x is not Cat` narrows the *true* branch to `not Cat`. +declare function isNotCat(x: unknown): x is not Cat; +>isNotCat : Symbol(isNotCat, Decl(negatedNarrowingTypePredicate.ts, 38, 1)) +>x : Symbol(x, Decl(negatedNarrowingTypePredicate.ts, 41, 26)) +>x : Symbol(x, Decl(negatedNarrowingTypePredicate.ts, 41, 26)) +>Cat : Symbol(Cat, Decl(negatedNarrowingTypePredicate.ts, 0, 0)) + +declare const c: {}; +>c : Symbol(c, Decl(negatedNarrowingTypePredicate.ts, 42, 13)) + +if (isNotCat(c)) { +>isNotCat : Symbol(isNotCat, Decl(negatedNarrowingTypePredicate.ts, 38, 1)) +>c : Symbol(c, Decl(negatedNarrowingTypePredicate.ts, 42, 13)) + + c; // {} & not Cat +>c : Symbol(c, Decl(negatedNarrowingTypePredicate.ts, 42, 13)) + + wantsNotCat(c); +>wantsNotCat : Symbol(wantsNotCat, Decl(negatedNarrowingTypePredicate.ts, 7, 45)) +>c : Symbol(c, Decl(negatedNarrowingTypePredicate.ts, 42, 13)) + +} else { + c; // {} & Cat +>c : Symbol(c, Decl(negatedNarrowingTypePredicate.ts, 42, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypePredicate.types b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypePredicate.types new file mode 100644 index 0000000000000..6698917937530 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypePredicate.types @@ -0,0 +1,110 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingTypePredicate.ts] //// + +=== negatedNarrowingTypePredicate.ts === +// Control flow narrowing by a user-defined type guard `x is T`. In the false branch a fresh +// `not T` is intersected in and survives where the base type overlaps T. + +interface Cat { + meow(): void; +>meow : () => void +} + +declare function isCat(x: unknown): x is Cat; +>isCat : (x: unknown) => x is Cat +>x : unknown + +declare function wantsNotCat(x: not Cat): void; +>wantsNotCat : (x: not Cat) => void +>x : not Cat + +// `{}` base overlaps Cat. +declare const a: {}; +>a : {} + +if (isCat(a)) { +>isCat(a) : boolean +>isCat : (x: unknown) => x is Cat +>a : {} + + a; // {} & Cat +>a : Cat + +} else { + a; // {} & not Cat +>a : {} & not Cat + + wantsNotCat(a); +>wantsNotCat(a) : void +>wantsNotCat : (x: not Cat) => void +>a : {} & not Cat +} + +// A bare type parameter. +function generic(x: T) { +>generic : (x: T) => void +>x : T + + if (isCat(x)) { +>isCat(x) : boolean +>isCat : (x: unknown) => x is Cat +>x : T + + x; // T & Cat +>x : T & Cat + + } else { + x; // T & not Cat +>x : T & not Cat + } +} + +// A disjoint union: `not Cat` reduces away against the non-Cat constituent. +interface Dog { + bark(): void; +>bark : () => void + + meow?: undefined; +>meow : undefined +} +declare const b: Cat | Dog; +>b : Cat | Dog + +if (isCat(b)) { +>isCat(b) : boolean +>isCat : (x: unknown) => x is Cat +>b : Cat | Dog + + b; // Cat +>b : Cat + +} else { + b; // Dog +>b : Dog +} + +// A negated type guard `x is not Cat` narrows the *true* branch to `not Cat`. +declare function isNotCat(x: unknown): x is not Cat; +>isNotCat : (x: unknown) => x is not Cat +>x : unknown + +declare const c: {}; +>c : {} + +if (isNotCat(c)) { +>isNotCat(c) : boolean +>isNotCat : (x: unknown) => x is not Cat +>c : {} + + c; // {} & not Cat +>c : {} & not Cat + + wantsNotCat(c); +>wantsNotCat(c) : void +>wantsNotCat : (x: not Cat) => void +>c : {} & not Cat + +} else { + c; // {} & Cat +>c : Cat +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypeof.symbols b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypeof.symbols new file mode 100644 index 0000000000000..fb0b3ffde60e4 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypeof.symbols @@ -0,0 +1,116 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingTypeof.ts] //// + +=== negatedNarrowingTypeof.ts === +// Control flow narrowing by `typeof x === "..."`. In the false branch a fresh `not ` +// is intersected in, but only survives where the base type overlaps the removed primitive. + +declare function wantsNotStr(x: not string): void; +>wantsNotStr : Symbol(wantsNotStr, Decl(negatedNarrowingTypeof.ts, 0, 0)) +>x : Symbol(x, Decl(negatedNarrowingTypeof.ts, 3, 29)) + +declare function wantsNotNum(x: not number): void; +>wantsNotNum : Symbol(wantsNotNum, Decl(negatedNarrowingTypeof.ts, 3, 50)) +>x : Symbol(x, Decl(negatedNarrowingTypeof.ts, 4, 29)) + +// `{}` overlaps every primitive, so the negation is retained. +declare const a: {}; +>a : Symbol(a, Decl(negatedNarrowingTypeof.ts, 7, 13)) + +if (typeof a === "string") { +>a : Symbol(a, Decl(negatedNarrowingTypeof.ts, 7, 13)) + + a; // string +>a : Symbol(a, Decl(negatedNarrowingTypeof.ts, 7, 13)) + +} else { + a; // {} & not string +>a : Symbol(a, Decl(negatedNarrowingTypeof.ts, 7, 13)) + + wantsNotStr(a); +>wantsNotStr : Symbol(wantsNotStr, Decl(negatedNarrowingTypeof.ts, 0, 0)) +>a : Symbol(a, Decl(negatedNarrowingTypeof.ts, 7, 13)) +} + +// `!==` flips the branches. +declare const b: {}; +>b : Symbol(b, Decl(negatedNarrowingTypeof.ts, 16, 13)) + +if (typeof b !== "number") { +>b : Symbol(b, Decl(negatedNarrowingTypeof.ts, 16, 13)) + + b; // {} & not number +>b : Symbol(b, Decl(negatedNarrowingTypeof.ts, 16, 13)) + + wantsNotNum(b); +>wantsNotNum : Symbol(wantsNotNum, Decl(negatedNarrowingTypeof.ts, 3, 50)) +>b : Symbol(b, Decl(negatedNarrowingTypeof.ts, 16, 13)) + +} else { + b; // number +>b : Symbol(b, Decl(negatedNarrowingTypeof.ts, 16, 13)) +} + +// A disjoint union: `not number` is redundant and reduces away. +declare const c: string | number; +>c : Symbol(c, Decl(negatedNarrowingTypeof.ts, 25, 13)) + +if (typeof c === "number") { +>c : Symbol(c, Decl(negatedNarrowingTypeof.ts, 25, 13)) + + c; // number +>c : Symbol(c, Decl(negatedNarrowingTypeof.ts, 25, 13)) + +} else { + c; // string +>c : Symbol(c, Decl(negatedNarrowingTypeof.ts, 25, 13)) +} + +// A bare type parameter retains the negation on each branch. +function generic(x: T) { +>generic : Symbol(generic, Decl(negatedNarrowingTypeof.ts, 30, 1)) +>T : Symbol(T, Decl(negatedNarrowingTypeof.ts, 33, 17)) +>x : Symbol(x, Decl(negatedNarrowingTypeof.ts, 33, 20)) +>T : Symbol(T, Decl(negatedNarrowingTypeof.ts, 33, 17)) + + if (typeof x === "boolean") { +>x : Symbol(x, Decl(negatedNarrowingTypeof.ts, 33, 20)) + + x; // T & boolean +>x : Symbol(x, Decl(negatedNarrowingTypeof.ts, 33, 20)) + + } else { + x; // T & not boolean +>x : Symbol(x, Decl(negatedNarrowingTypeof.ts, 33, 20)) + } +} + +// `unknown` narrows to the primitive on the true branch and keeps a negation on the false branch. +declare const u: unknown; +>u : Symbol(u, Decl(negatedNarrowingTypeof.ts, 42, 13)) + +if (typeof u === "string") { +>u : Symbol(u, Decl(negatedNarrowingTypeof.ts, 42, 13)) + + u; // string +>u : Symbol(u, Decl(negatedNarrowingTypeof.ts, 42, 13)) + +} else { + u; // (unknown narrowed) & not string +>u : Symbol(u, Decl(negatedNarrowingTypeof.ts, 42, 13)) +} + +// `==` / `!=` behave like their strict counterparts here. +declare const d: {}; +>d : Symbol(d, Decl(negatedNarrowingTypeof.ts, 50, 13)) + +if (typeof d == "bigint") { +>d : Symbol(d, Decl(negatedNarrowingTypeof.ts, 50, 13)) + + d; // bigint +>d : Symbol(d, Decl(negatedNarrowingTypeof.ts, 50, 13)) + +} else { + d; // {} & not bigint +>d : Symbol(d, Decl(negatedNarrowingTypeof.ts, 50, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypeof.types b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypeof.types new file mode 100644 index 0000000000000..2786fe47ca47e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedNarrowingTypeof.types @@ -0,0 +1,134 @@ +//// [tests/cases/conformance/types/negated/negatedNarrowingTypeof.ts] //// + +=== negatedNarrowingTypeof.ts === +// Control flow narrowing by `typeof x === "..."`. In the false branch a fresh `not ` +// is intersected in, but only survives where the base type overlaps the removed primitive. + +declare function wantsNotStr(x: not string): void; +>wantsNotStr : (x: not string) => void +>x : not string + +declare function wantsNotNum(x: not number): void; +>wantsNotNum : (x: not number) => void +>x : not number + +// `{}` overlaps every primitive, so the negation is retained. +declare const a: {}; +>a : {} + +if (typeof a === "string") { +>typeof a === "string" : boolean +>typeof a : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>a : {} +>"string" : "string" + + a; // string +>a : string + +} else { + a; // {} & not string +>a : {} & not string + + wantsNotStr(a); +>wantsNotStr(a) : void +>wantsNotStr : (x: not string) => void +>a : {} & not string +} + +// `!==` flips the branches. +declare const b: {}; +>b : {} + +if (typeof b !== "number") { +>typeof b !== "number" : boolean +>typeof b : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>b : {} +>"number" : "number" + + b; // {} & not number +>b : {} & not number + + wantsNotNum(b); +>wantsNotNum(b) : void +>wantsNotNum : (x: not number) => void +>b : {} & not number + +} else { + b; // number +>b : number +} + +// A disjoint union: `not number` is redundant and reduces away. +declare const c: string | number; +>c : string | number + +if (typeof c === "number") { +>typeof c === "number" : boolean +>typeof c : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>c : string | number +>"number" : "number" + + c; // number +>c : number + +} else { + c; // string +>c : string +} + +// A bare type parameter retains the negation on each branch. +function generic(x: T) { +>generic : (x: T) => void +>x : T + + if (typeof x === "boolean") { +>typeof x === "boolean" : boolean +>typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>x : T +>"boolean" : "boolean" + + x; // T & boolean +>x : T & boolean + + } else { + x; // T & not boolean +>x : T & not false & not true + } +} + +// `unknown` narrows to the primitive on the true branch and keeps a negation on the false branch. +declare const u: unknown; +>u : unknown + +if (typeof u === "string") { +>typeof u === "string" : boolean +>typeof u : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>u : unknown +>"string" : "string" + + u; // string +>u : string + +} else { + u; // (unknown narrowed) & not string +>u : not string +} + +// `==` / `!=` behave like their strict counterparts here. +declare const d: {}; +>d : {} + +if (typeof d == "bigint") { +>typeof d == "bigint" : boolean +>typeof d : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>d : {} +>"bigint" : "bigint" + + d; // bigint +>d : bigint + +} else { + d; // {} & not bigint +>d : {} & not bigint +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.errors.txt new file mode 100644 index 0000000000000..53197a08b0704 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.errors.txt @@ -0,0 +1,107 @@ +negatedPromiseRepr.ts(10,39): error TS2344: Type 'T extends MyPromiseLike ? AwaitValue : T' does not satisfy the constraint 'not AnyPromiseLikeObject'. + Type 'T | AwaitValue' is not assignable to type 'not AnyPromiseLikeObject'. + Type 'T' is not assignable to type 'not AnyPromiseLikeObject'. +negatedPromiseRepr.ts(16,56): error TS2344: Type 'AwaitValue' does not satisfy the constraint 'not AnyPromiseLikeObject'. + Type 'T | not AnyPromiseLikeObject' is not assignable to type 'not AnyPromiseLikeObject'. + Type 'T' is not assignable to type 'not AnyPromiseLikeObject'. +negatedPromiseRepr.ts(26,18): error TS2344: Type 'AwaitValue' does not satisfy the constraint 'not AnyPromiseLikeObject'. + Type 'U | not AnyPromiseLikeObject' is not assignable to type 'not AnyPromiseLikeObject'. + Type 'U' is not assignable to type 'not AnyPromiseLikeObject'. +negatedPromiseRepr.ts(30,18): error TS2344: Type 'T | AwaitValue' does not satisfy the constraint 'not AnyPromiseLikeObject'. + Type 'AwaitValue' is not assignable to type 'not AnyPromiseLikeObject'. + Type 'U | not AnyPromiseLikeObject' is not assignable to type 'not AnyPromiseLikeObject'. + Type 'U' is not assignable to type 'not AnyPromiseLikeObject'. +negatedPromiseRepr.ts(34,18): error TS2344: Type 'AwaitValue' does not satisfy the constraint 'not AnyPromiseLikeObject'. + Type 'U | not AnyPromiseLikeObject' is not assignable to type 'not AnyPromiseLikeObject'. + Type 'U' is not assignable to type 'not AnyPromiseLikeObject'. +negatedPromiseRepr.ts(37,18): error TS2344: Type 'T | AwaitValue' does not satisfy the constraint 'not AnyPromiseLikeObject'. + Type 'AwaitValue' is not assignable to type 'not AnyPromiseLikeObject'. + Type 'U | not AnyPromiseLikeObject' is not assignable to type 'not AnyPromiseLikeObject'. + Type 'U' is not assignable to type 'not AnyPromiseLikeObject'. + + +==== negatedPromiseRepr.ts (6 errors) ==== + // inspired by a comment in https://github.com/Microsoft/TypeScript/issues/4196 + + type AnyPromiseLikeObject = object & MyPromiseLike; + interface MyPromiseLike { + then(onResolve: (value: T) => any, onReject: (error: E) => any): any; + } + + type AwaitValue = T extends MyPromiseLike ? U : T; + + type CoercePromiseLike = MyPromise ? AwaitValue : T, never>; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'T extends MyPromiseLike ? AwaitValue : T' does not satisfy the constraint 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'T | AwaitValue' is not assignable to type 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'T' is not assignable to type 'not AnyPromiseLikeObject'. +!!! related TS2208 negatedPromiseRepr.ts:10:24: This type parameter might need an `extends not AnyPromiseLikeObject` constraint. + + interface MyPromiseConstructor { + resolve(value: T): CoercePromiseLike; + reject(value: E): MyPromise; + all(values: Iterable): MyPromise[] & not AnyPromiseLikeObject, E>; + race(values: Iterable): MyPromise, E>; + ~~~~~~~~~~~~~ +!!! error TS2344: Type 'AwaitValue' does not satisfy the constraint 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'T | not AnyPromiseLikeObject' is not assignable to type 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'T' is not assignable to type 'not AnyPromiseLikeObject'. +!!! related TS2208 negatedPromiseRepr.ts:16:10: This type parameter might need an `extends not AnyPromiseLikeObject` constraint. + } + declare var MyPromise: MyPromiseConstructor; + + interface MyPromise { + then(onResolve?: not Function, onReject?: not Function): MyPromise; + catch(onReject?: not Function): MyPromise; + then( + onResolve: (value: AwaitValue) => U, + onReject?: not Function, + ): MyPromise, E | F>; + ~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'AwaitValue' does not satisfy the constraint 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'U | not AnyPromiseLikeObject' is not assignable to type 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'U' is not assignable to type 'not AnyPromiseLikeObject'. +!!! related TS2208 negatedPromiseRepr.ts:23:10: This type parameter might need an `extends not AnyPromiseLikeObject` constraint. + then( + onResolve: not Function, + onReject: (error: E) => U, + ): MyPromise, F>; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'T | AwaitValue' does not satisfy the constraint 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'AwaitValue' is not assignable to type 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'U | not AnyPromiseLikeObject' is not assignable to type 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'U' is not assignable to type 'not AnyPromiseLikeObject'. +!!! related TS2208 negatedPromiseRepr.ts:27:10: This type parameter might need an `extends not AnyPromiseLikeObject` constraint. + then( + onResolve: (value: AwaitValue) => U, + onReject: (error: E) => AwaitValue, + ): MyPromise, F>; + ~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'AwaitValue' does not satisfy the constraint 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'U | not AnyPromiseLikeObject' is not assignable to type 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'U' is not assignable to type 'not AnyPromiseLikeObject'. +!!! related TS2208 negatedPromiseRepr.ts:31:10: This type parameter might need an `extends not AnyPromiseLikeObject` constraint. + catch( + onReject: (error: E) => U, + ): MyPromise, F>; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'T | AwaitValue' does not satisfy the constraint 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'AwaitValue' is not assignable to type 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'U | not AnyPromiseLikeObject' is not assignable to type 'not AnyPromiseLikeObject'. +!!! error TS2344: Type 'U' is not assignable to type 'not AnyPromiseLikeObject'. +!!! related TS2208 negatedPromiseRepr.ts:35:11: This type parameter might need an `extends not AnyPromiseLikeObject` constraint. + finally(onSettled: () => AnyPromiseLikeObject): MyPromise; + } + + const a = MyPromise.resolve(0); + + const b = MyPromise.resolve(MyPromise.resolve(0)); + + const d = MyPromise.resolve(MyPromise.resolve(MyPromise.resolve(0))); + + const e = MyPromise.resolve(0).then(x => "ok"); + + const f = MyPromise.all([1, 2, 3, Promise.resolve("ok")]); + + const g = MyPromise.race([1, 2, 3, Promise.resolve("ok")]); + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.js b/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.js new file mode 100644 index 0000000000000..91705bd5bc9f6 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.js @@ -0,0 +1,65 @@ +//// [tests/cases/conformance/types/negated/negatedPromiseRepr.ts] //// + +//// [negatedPromiseRepr.ts] +// inspired by a comment in https://github.com/Microsoft/TypeScript/issues/4196 + +type AnyPromiseLikeObject = object & MyPromiseLike; +interface MyPromiseLike { + then(onResolve: (value: T) => any, onReject: (error: E) => any): any; +} + +type AwaitValue = T extends MyPromiseLike ? U : T; + +type CoercePromiseLike = MyPromise ? AwaitValue : T, never>; + +interface MyPromiseConstructor { + resolve(value: T): CoercePromiseLike; + reject(value: E): MyPromise; + all(values: Iterable): MyPromise[] & not AnyPromiseLikeObject, E>; + race(values: Iterable): MyPromise, E>; +} +declare var MyPromise: MyPromiseConstructor; + +interface MyPromise { + then(onResolve?: not Function, onReject?: not Function): MyPromise; + catch(onReject?: not Function): MyPromise; + then( + onResolve: (value: AwaitValue) => U, + onReject?: not Function, + ): MyPromise, E | F>; + then( + onResolve: not Function, + onReject: (error: E) => U, + ): MyPromise, F>; + then( + onResolve: (value: AwaitValue) => U, + onReject: (error: E) => AwaitValue, + ): MyPromise, F>; + catch( + onReject: (error: E) => U, + ): MyPromise, F>; + finally(onSettled: () => AnyPromiseLikeObject): MyPromise; +} + +const a = MyPromise.resolve(0); + +const b = MyPromise.resolve(MyPromise.resolve(0)); + +const d = MyPromise.resolve(MyPromise.resolve(MyPromise.resolve(0))); + +const e = MyPromise.resolve(0).then(x => "ok"); + +const f = MyPromise.all([1, 2, 3, Promise.resolve("ok")]); + +const g = MyPromise.race([1, 2, 3, Promise.resolve("ok")]); + + +//// [negatedPromiseRepr.js] +"use strict"; +// inspired by a comment in https://github.com/Microsoft/TypeScript/issues/4196 +const a = MyPromise.resolve(0); +const b = MyPromise.resolve(MyPromise.resolve(0)); +const d = MyPromise.resolve(MyPromise.resolve(MyPromise.resolve(0))); +const e = MyPromise.resolve(0).then(x => "ok"); +const f = MyPromise.all([1, 2, 3, Promise.resolve("ok")]); +const g = MyPromise.race([1, 2, 3, Promise.resolve("ok")]); diff --git a/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.symbols b/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.symbols new file mode 100644 index 0000000000000..e110d6c9a2e76 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.symbols @@ -0,0 +1,283 @@ +//// [tests/cases/conformance/types/negated/negatedPromiseRepr.ts] //// + +=== negatedPromiseRepr.ts === +// inspired by a comment in https://github.com/Microsoft/TypeScript/issues/4196 + +type AnyPromiseLikeObject = object & MyPromiseLike; +>AnyPromiseLikeObject : Symbol(AnyPromiseLikeObject, Decl(negatedPromiseRepr.ts, 0, 0)) +>MyPromiseLike : Symbol(MyPromiseLike, Decl(negatedPromiseRepr.ts, 2, 61)) + +interface MyPromiseLike { +>MyPromiseLike : Symbol(MyPromiseLike, Decl(negatedPromiseRepr.ts, 2, 61)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 3, 24)) +>AnyPromiseLikeObject : Symbol(AnyPromiseLikeObject, Decl(negatedPromiseRepr.ts, 0, 0)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 3, 59)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + then(onResolve: (value: T) => any, onReject: (error: E) => any): any; +>then : Symbol(MyPromiseLike.then, Decl(negatedPromiseRepr.ts, 3, 72)) +>onResolve : Symbol(onResolve, Decl(negatedPromiseRepr.ts, 4, 9)) +>value : Symbol(value, Decl(negatedPromiseRepr.ts, 4, 21)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 3, 24)) +>onReject : Symbol(onReject, Decl(negatedPromiseRepr.ts, 4, 38)) +>error : Symbol(error, Decl(negatedPromiseRepr.ts, 4, 50)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 3, 59)) +} + +type AwaitValue = T extends MyPromiseLike ? U : T; +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 7, 16)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 7, 18)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 7, 16)) +>MyPromiseLike : Symbol(MyPromiseLike, Decl(negatedPromiseRepr.ts, 2, 61)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 7, 59)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 7, 18)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 7, 59)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 7, 16)) + +type CoercePromiseLike = MyPromise ? AwaitValue : T, never>; +>CoercePromiseLike : Symbol(CoercePromiseLike, Decl(negatedPromiseRepr.ts, 7, 74)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 9, 23)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 9, 23)) +>MyPromiseLike : Symbol(MyPromiseLike, Decl(negatedPromiseRepr.ts, 2, 61)) +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 9, 23)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 9, 23)) + +interface MyPromiseConstructor { +>MyPromiseConstructor : Symbol(MyPromiseConstructor, Decl(negatedPromiseRepr.ts, 9, 100)) + + resolve(value: T): CoercePromiseLike; +>resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 12, 12)) +>value : Symbol(value, Decl(negatedPromiseRepr.ts, 12, 15)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 12, 12)) +>CoercePromiseLike : Symbol(CoercePromiseLike, Decl(negatedPromiseRepr.ts, 7, 74)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 12, 12)) + + reject(value: E): MyPromise; +>reject : Symbol(MyPromiseConstructor.reject, Decl(negatedPromiseRepr.ts, 12, 47)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 13, 11)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>value : Symbol(value, Decl(negatedPromiseRepr.ts, 13, 22)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 13, 11)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 13, 11)) + + all(values: Iterable): MyPromise[] & not AnyPromiseLikeObject, E>; +>all : Symbol(MyPromiseConstructor.all, Decl(negatedPromiseRepr.ts, 13, 53)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 14, 8)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 14, 10)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>values : Symbol(values, Decl(negatedPromiseRepr.ts, 14, 22)) +>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 14, 8)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 14, 8)) +>AnyPromiseLikeObject : Symbol(AnyPromiseLikeObject, Decl(negatedPromiseRepr.ts, 0, 0)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 14, 10)) + + race(values: Iterable): MyPromise, E>; +>race : Symbol(MyPromiseConstructor.race, Decl(negatedPromiseRepr.ts, 14, 101)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 15, 9)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 15, 11)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>values : Symbol(values, Decl(negatedPromiseRepr.ts, 15, 23)) +>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 15, 9)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 15, 9)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 15, 11)) +} +declare var MyPromise: MyPromiseConstructor; +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>MyPromiseConstructor : Symbol(MyPromiseConstructor, Decl(negatedPromiseRepr.ts, 9, 100)) + +interface MyPromise { +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 19, 20)) +>AnyPromiseLikeObject : Symbol(AnyPromiseLikeObject, Decl(negatedPromiseRepr.ts, 0, 0)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + then(onResolve?: not Function, onReject?: not Function): MyPromise; +>then : Symbol(MyPromise.then, Decl(negatedPromiseRepr.ts, 19, 68), Decl(negatedPromiseRepr.ts, 21, 52), Decl(negatedPromiseRepr.ts, 25, 42), Decl(negatedPromiseRepr.ts, 29, 42)) +>onResolve : Symbol(onResolve, Decl(negatedPromiseRepr.ts, 20, 9)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>onReject : Symbol(onReject, Decl(negatedPromiseRepr.ts, 20, 34)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 19, 20)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) + + catch(onReject?: not Function): MyPromise; +>catch : Symbol(MyPromise.catch, Decl(negatedPromiseRepr.ts, 20, 77), Decl(negatedPromiseRepr.ts, 33, 38)) +>onReject : Symbol(onReject, Decl(negatedPromiseRepr.ts, 21, 10)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 19, 20)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) + + then( +>then : Symbol(MyPromise.then, Decl(negatedPromiseRepr.ts, 19, 68), Decl(negatedPromiseRepr.ts, 21, 52), Decl(negatedPromiseRepr.ts, 25, 42), Decl(negatedPromiseRepr.ts, 29, 42)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 22, 9)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 22, 11)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) + + onResolve: (value: AwaitValue) => U, +>onResolve : Symbol(onResolve, Decl(negatedPromiseRepr.ts, 22, 19)) +>value : Symbol(value, Decl(negatedPromiseRepr.ts, 23, 20)) +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 19, 20)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 22, 9)) + + onReject?: not Function, +>onReject : Symbol(onReject, Decl(negatedPromiseRepr.ts, 23, 47)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ): MyPromise, E | F>; +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 22, 9)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 22, 11)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 22, 11)) + + then( +>then : Symbol(MyPromise.then, Decl(negatedPromiseRepr.ts, 19, 68), Decl(negatedPromiseRepr.ts, 21, 52), Decl(negatedPromiseRepr.ts, 25, 42), Decl(negatedPromiseRepr.ts, 29, 42)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 26, 9)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 26, 11)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) + + onResolve: not Function, +>onResolve : Symbol(onResolve, Decl(negatedPromiseRepr.ts, 26, 19)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + onReject: (error: E) => U, +>onReject : Symbol(onReject, Decl(negatedPromiseRepr.ts, 27, 32)) +>error : Symbol(error, Decl(negatedPromiseRepr.ts, 28, 19)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 26, 9)) + + ): MyPromise, F>; +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 19, 20)) +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 26, 9)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 26, 11)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 26, 11)) + + then( +>then : Symbol(MyPromise.then, Decl(negatedPromiseRepr.ts, 19, 68), Decl(negatedPromiseRepr.ts, 21, 52), Decl(negatedPromiseRepr.ts, 25, 42), Decl(negatedPromiseRepr.ts, 29, 42)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 30, 9)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 30, 11)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) + + onResolve: (value: AwaitValue) => U, +>onResolve : Symbol(onResolve, Decl(negatedPromiseRepr.ts, 30, 19)) +>value : Symbol(value, Decl(negatedPromiseRepr.ts, 31, 20)) +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 19, 20)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 30, 9)) + + onReject: (error: E) => AwaitValue, +>onReject : Symbol(onReject, Decl(negatedPromiseRepr.ts, 31, 47)) +>error : Symbol(error, Decl(negatedPromiseRepr.ts, 32, 19)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 30, 9)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 30, 11)) + + ): MyPromise, F>; +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 30, 9)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 30, 11)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 30, 11)) + + catch( +>catch : Symbol(MyPromise.catch, Decl(negatedPromiseRepr.ts, 20, 77), Decl(negatedPromiseRepr.ts, 33, 38)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 34, 10)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 34, 12)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) + + onReject: (error: E) => U, +>onReject : Symbol(onReject, Decl(negatedPromiseRepr.ts, 34, 20)) +>error : Symbol(error, Decl(negatedPromiseRepr.ts, 35, 19)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 34, 10)) + + ): MyPromise, F>; +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 19, 20)) +>AwaitValue : Symbol(AwaitValue, Decl(negatedPromiseRepr.ts, 5, 1)) +>U : Symbol(U, Decl(negatedPromiseRepr.ts, 34, 10)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 34, 12)) +>F : Symbol(F, Decl(negatedPromiseRepr.ts, 34, 12)) + + finally(onSettled: () => AnyPromiseLikeObject): MyPromise; +>finally : Symbol(MyPromise.finally, Decl(negatedPromiseRepr.ts, 36, 42)) +>onSettled : Symbol(onSettled, Decl(negatedPromiseRepr.ts, 37, 12)) +>AnyPromiseLikeObject : Symbol(AnyPromiseLikeObject, Decl(negatedPromiseRepr.ts, 0, 0)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>T : Symbol(T, Decl(negatedPromiseRepr.ts, 19, 20)) +>E : Symbol(E, Decl(negatedPromiseRepr.ts, 19, 55)) +} + +const a = MyPromise.resolve(0); +>a : Symbol(a, Decl(negatedPromiseRepr.ts, 40, 5)) +>MyPromise.resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) + +const b = MyPromise.resolve(MyPromise.resolve(0)); +>b : Symbol(b, Decl(negatedPromiseRepr.ts, 42, 5)) +>MyPromise.resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>MyPromise.resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) + +const d = MyPromise.resolve(MyPromise.resolve(MyPromise.resolve(0))); +>d : Symbol(d, Decl(negatedPromiseRepr.ts, 44, 5)) +>MyPromise.resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>MyPromise.resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>MyPromise.resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) + +const e = MyPromise.resolve(0).then(x => "ok"); +>e : Symbol(e, Decl(negatedPromiseRepr.ts, 46, 5)) +>MyPromise.resolve(0).then : Symbol(MyPromise.then, Decl(negatedPromiseRepr.ts, 19, 68), Decl(negatedPromiseRepr.ts, 21, 52), Decl(negatedPromiseRepr.ts, 25, 42), Decl(negatedPromiseRepr.ts, 29, 42)) +>MyPromise.resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>resolve : Symbol(MyPromiseConstructor.resolve, Decl(negatedPromiseRepr.ts, 11, 32)) +>then : Symbol(MyPromise.then, Decl(negatedPromiseRepr.ts, 19, 68), Decl(negatedPromiseRepr.ts, 21, 52), Decl(negatedPromiseRepr.ts, 25, 42), Decl(negatedPromiseRepr.ts, 29, 42)) +>x : Symbol(x, Decl(negatedPromiseRepr.ts, 46, 36)) + +const f = MyPromise.all([1, 2, 3, Promise.resolve("ok")]); +>f : Symbol(f, Decl(negatedPromiseRepr.ts, 48, 5)) +>MyPromise.all : Symbol(MyPromiseConstructor.all, Decl(negatedPromiseRepr.ts, 13, 53)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>all : Symbol(MyPromiseConstructor.all, Decl(negatedPromiseRepr.ts, 13, 53)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + +const g = MyPromise.race([1, 2, 3, Promise.resolve("ok")]); +>g : Symbol(g, Decl(negatedPromiseRepr.ts, 50, 5)) +>MyPromise.race : Symbol(MyPromiseConstructor.race, Decl(negatedPromiseRepr.ts, 14, 101)) +>MyPromise : Symbol(MyPromise, Decl(negatedPromiseRepr.ts, 17, 11), Decl(negatedPromiseRepr.ts, 17, 44)) +>race : Symbol(MyPromiseConstructor.race, Decl(negatedPromiseRepr.ts, 14, 101)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.types b/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.types new file mode 100644 index 0000000000000..0622304e206fc --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedPromiseRepr.types @@ -0,0 +1,182 @@ +//// [tests/cases/conformance/types/negated/negatedPromiseRepr.ts] //// + +=== negatedPromiseRepr.ts === +// inspired by a comment in https://github.com/Microsoft/TypeScript/issues/4196 + +type AnyPromiseLikeObject = object & MyPromiseLike; +>AnyPromiseLikeObject : AnyPromiseLikeObject + +interface MyPromiseLike { + then(onResolve: (value: T) => any, onReject: (error: E) => any): any; +>then : (onResolve: (value: T) => any, onReject: (error: E) => any) => any +>onResolve : (value: T) => any +>value : T +>onReject : (error: E) => any +>error : E +} + +type AwaitValue = T extends MyPromiseLike ? U : T; +>AwaitValue : AwaitValue + +type CoercePromiseLike = MyPromise ? AwaitValue : T, never>; +>CoercePromiseLike : CoercePromiseLike + +interface MyPromiseConstructor { + resolve(value: T): CoercePromiseLike; +>resolve : (value: T) => CoercePromiseLike +>value : T + + reject(value: E): MyPromise; +>reject : (value: E) => MyPromise +>value : E + + all(values: Iterable): MyPromise[] & not AnyPromiseLikeObject, E>; +>all : (values: Iterable) => MyPromise[] & not AnyPromiseLikeObject, E> +>values : Iterable + + race(values: Iterable): MyPromise, E>; +>race : (values: Iterable) => MyPromise, E> +>values : Iterable +} +declare var MyPromise: MyPromiseConstructor; +>MyPromise : MyPromiseConstructor + +interface MyPromise { + then(onResolve?: not Function, onReject?: not Function): MyPromise; +>then : { (onResolve?: not Function, onReject?: not Function): MyPromise; (onResolve: (value: AwaitValue) => U, onReject?: not Function): MyPromise, E | F>; (onResolve: not Function, onReject: (error: E) => U): MyPromise, F>; (onResolve: (value: AwaitValue) => U, onReject: (error: E) => AwaitValue): MyPromise, F>; } +>onResolve : not Function | undefined +>onReject : not Function | undefined + + catch(onReject?: not Function): MyPromise; +>catch : { (onReject?: not Function): MyPromise; (onReject: (error: E) => U): MyPromise, F>; } +>onReject : not Function | undefined + + then( +>then : { (onResolve?: not Function, onReject?: not Function): MyPromise; (onResolve: (value: AwaitValue) => U, onReject?: not Function): MyPromise, E | F>; (onResolve: not Function, onReject: (error: E) => U_1): MyPromise, F_1>; (onResolve: (value: AwaitValue) => U_1, onReject: (error: E) => AwaitValue): MyPromise, F_1>; } + + onResolve: (value: AwaitValue) => U, +>onResolve : (value: AwaitValue) => U +>value : AwaitValue + + onReject?: not Function, +>onReject : not Function | undefined + + ): MyPromise, E | F>; + then( +>then : { (onResolve?: not Function, onReject?: not Function): MyPromise; (onResolve: (value: AwaitValue) => U_1, onReject?: not Function): MyPromise, E | F_1>; (onResolve: not Function, onReject: (error: E) => U): MyPromise, F>; (onResolve: (value: AwaitValue) => U_1, onReject: (error: E) => AwaitValue): MyPromise, F_1>; } + + onResolve: not Function, +>onResolve : not Function + + onReject: (error: E) => U, +>onReject : (error: E) => U +>error : E + + ): MyPromise, F>; + then( +>then : { (onResolve?: not Function, onReject?: not Function): MyPromise; (onResolve: (value: AwaitValue) => U_1, onReject?: not Function): MyPromise, E | F_1>; (onResolve: not Function, onReject: (error: E) => U_1): MyPromise, F_1>; (onResolve: (value: AwaitValue) => U, onReject: (error: E) => AwaitValue): MyPromise, F>; } + + onResolve: (value: AwaitValue) => U, +>onResolve : (value: AwaitValue) => U +>value : AwaitValue + + onReject: (error: E) => AwaitValue, +>onReject : (error: E) => AwaitValue +>error : E + + ): MyPromise, F>; + catch( +>catch : { (onReject?: not Function): MyPromise; (onReject: (error: E) => U): MyPromise, F>; } + + onReject: (error: E) => U, +>onReject : (error: E) => U +>error : E + + ): MyPromise, F>; + finally(onSettled: () => AnyPromiseLikeObject): MyPromise; +>finally : (onSettled: () => AnyPromiseLikeObject) => MyPromise +>onSettled : () => AnyPromiseLikeObject +} + +const a = MyPromise.resolve(0); +>a : CoercePromiseLike +>MyPromise.resolve(0) : CoercePromiseLike +>MyPromise.resolve : (value: T) => CoercePromiseLike +>MyPromise : MyPromiseConstructor +>resolve : (value: T) => CoercePromiseLike +>0 : 0 + +const b = MyPromise.resolve(MyPromise.resolve(0)); +>b : CoercePromiseLike> +>MyPromise.resolve(MyPromise.resolve(0)) : CoercePromiseLike> +>MyPromise.resolve : (value: T) => CoercePromiseLike +>MyPromise : MyPromiseConstructor +>resolve : (value: T) => CoercePromiseLike +>MyPromise.resolve(0) : CoercePromiseLike +>MyPromise.resolve : (value: T) => CoercePromiseLike +>MyPromise : MyPromiseConstructor +>resolve : (value: T) => CoercePromiseLike +>0 : 0 + +const d = MyPromise.resolve(MyPromise.resolve(MyPromise.resolve(0))); +>d : CoercePromiseLike>> +>MyPromise.resolve(MyPromise.resolve(MyPromise.resolve(0))) : CoercePromiseLike>> +>MyPromise.resolve : (value: T) => CoercePromiseLike +>MyPromise : MyPromiseConstructor +>resolve : (value: T) => CoercePromiseLike +>MyPromise.resolve(MyPromise.resolve(0)) : CoercePromiseLike> +>MyPromise.resolve : (value: T) => CoercePromiseLike +>MyPromise : MyPromiseConstructor +>resolve : (value: T) => CoercePromiseLike +>MyPromise.resolve(0) : CoercePromiseLike +>MyPromise.resolve : (value: T) => CoercePromiseLike +>MyPromise : MyPromiseConstructor +>resolve : (value: T) => CoercePromiseLike +>0 : 0 + +const e = MyPromise.resolve(0).then(x => "ok"); +>e : MyPromise +>MyPromise.resolve(0).then(x => "ok") : MyPromise +>MyPromise.resolve(0).then : { (onResolve?: not Function, onReject?: not Function): MyPromise; (onResolve: (value: number) => U, onReject?: not Function): MyPromise, F>; (onResolve: not Function, onReject: (error: never) => U): MyPromise, F>; (onResolve: (value: number) => U, onReject: (error: never) => AwaitValue): MyPromise, F>; } +>MyPromise.resolve(0) : CoercePromiseLike +>MyPromise.resolve : (value: T) => CoercePromiseLike +>MyPromise : MyPromiseConstructor +>resolve : (value: T) => CoercePromiseLike +>0 : 0 +>then : { (onResolve?: not Function, onReject?: not Function): MyPromise; (onResolve: (value: number) => U, onReject?: not Function): MyPromise, F>; (onResolve: not Function, onReject: (error: never) => U): MyPromise, F>; (onResolve: (value: number) => U, onReject: (error: never) => AwaitValue): MyPromise, F>; } +>x => "ok" : (x: number) => string +>x : number +>"ok" : "ok" + +const f = MyPromise.all([1, 2, 3, Promise.resolve("ok")]); +>f : MyPromise<(string | number)[] & not AnyPromiseLikeObject, Error> +>MyPromise.all([1, 2, 3, Promise.resolve("ok")]) : MyPromise<(string | number)[] & not AnyPromiseLikeObject, Error> +>MyPromise.all : (values: Iterable) => MyPromise[] & not AnyPromiseLikeObject, E> +>MyPromise : MyPromiseConstructor +>all : (values: Iterable) => MyPromise[] & not AnyPromiseLikeObject, E> +>[1, 2, 3, Promise.resolve("ok")] : (number | Promise)[] +>1 : 1 +>2 : 2 +>3 : 3 +>Promise.resolve("ok") : Promise +>Promise.resolve : { (): Promise; (value: T): Promise>; (value: T | PromiseLike): Promise>; } +>Promise : PromiseConstructor +>resolve : { (): Promise; (value: T): Promise>; (value: T | PromiseLike): Promise>; } +>"ok" : "ok" + +const g = MyPromise.race([1, 2, 3, Promise.resolve("ok")]); +>g : MyPromise +>MyPromise.race([1, 2, 3, Promise.resolve("ok")]) : MyPromise +>MyPromise.race : (values: Iterable) => MyPromise, E> +>MyPromise : MyPromiseConstructor +>race : (values: Iterable) => MyPromise, E> +>[1, 2, 3, Promise.resolve("ok")] : (number | Promise)[] +>1 : 1 +>2 : 2 +>3 : 3 +>Promise.resolve("ok") : Promise +>Promise.resolve : { (): Promise; (value: T): Promise>; (value: T | PromiseLike): Promise>; } +>Promise : PromiseConstructor +>resolve : { (): Promise; (value: T): Promise>; (value: T | PromiseLike): Promise>; } +>"ok" : "ok" + diff --git a/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.errors.txt new file mode 100644 index 0000000000000..9e1b996224c55 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.errors.txt @@ -0,0 +1,60 @@ +negatedRepresentativeExamples.ts(7,8): error TS2345: Argument of type 'Promise' is not assignable to parameter of type 'not (object & Promise)'. +negatedRepresentativeExamples.ts(14,16): error TS2345: Argument of type '() => void' is not assignable to parameter of type '(value: number) => not void'. + Type 'void' is not assignable to type 'not void'. +negatedRepresentativeExamples.ts(23,9): error TS2345: Argument of type 'number | null' is not assignable to parameter of type 'not null'. + Type 'null' is not assignable to type 'not null'. +negatedRepresentativeExamples.ts(23,17): error TS2365: Operator '>=' cannot be applied to types 'not null' and 'number'. +negatedRepresentativeExamples.ts(32,7): error TS2345: Argument of type '(number | undefined)[]' is not assignable to parameter of type '(not undefined)[]'. + Type 'number | undefined' is not assignable to type 'not undefined'. + Type 'undefined' is not assignable to type 'not undefined'. + + +==== negatedRepresentativeExamples.ts (5 errors) ==== + // https://github.com/Microsoft/TypeScript/issues/7993 + + declare function ignore)>(value: T): void; + declare function readFileAsync(): Promise; + declare function readFileSync(): string; + ignore(readFileSync()); // OK + ignore(readFileAsync()); // Should error + ~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'Promise' is not assignable to parameter of type 'not (object & Promise)'. +!!! related TS2773 negatedRepresentativeExamples.ts:7:8: Did you forget to use 'await'? + + declare function map(values: T[], map: (value: T) => U) : U[]; // validate map callback doesn't return void + + function foo() {} + + map([1, 2, 3], n => n + 1); // OK + map([1, 2, 3], foo); // Should error + ~~~ +!!! error TS2345: Argument of type '() => void' is not assignable to parameter of type '(value: number) => not void'. +!!! error TS2345: Type 'void' is not assignable to type 'not void'. + + function asValid(value: T, isValid: (value: T) => boolean) : T | null { + return isValid(value) ? value : null; + } + + declare const x: number; + declare const y: number | null; + asValid(x, n => n >= 0); // OK + asValid(y, n => n >= 0); // Should error + ~ +!!! error TS2345: Argument of type 'number | null' is not assignable to parameter of type 'not null'. +!!! error TS2345: Type 'null' is not assignable to type 'not null'. + ~~~~~~ +!!! error TS2365: Operator '>=' cannot be applied to types 'not null' and 'number'. + + function tryAt(values: T[], index: number): T | undefined { + return values[index]; + } + + declare const a: number[]; + declare const b: (number | undefined)[]; + tryAt(a, 0); // OK + tryAt(b, 0); // Should error + ~ +!!! error TS2345: Argument of type '(number | undefined)[]' is not assignable to parameter of type '(not undefined)[]'. +!!! error TS2345: Type 'number | undefined' is not assignable to type 'not undefined'. +!!! error TS2345: Type 'undefined' is not assignable to type 'not undefined'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.js b/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.js new file mode 100644 index 0000000000000..a7f28576fc1d2 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.js @@ -0,0 +1,55 @@ +//// [tests/cases/conformance/types/negated/negatedRepresentativeExamples.ts] //// + +//// [negatedRepresentativeExamples.ts] +// https://github.com/Microsoft/TypeScript/issues/7993 + +declare function ignore)>(value: T): void; +declare function readFileAsync(): Promise; +declare function readFileSync(): string; +ignore(readFileSync()); // OK +ignore(readFileAsync()); // Should error + +declare function map(values: T[], map: (value: T) => U) : U[]; // validate map callback doesn't return void + +function foo() {} + +map([1, 2, 3], n => n + 1); // OK +map([1, 2, 3], foo); // Should error + +function asValid(value: T, isValid: (value: T) => boolean) : T | null { + return isValid(value) ? value : null; +} + +declare const x: number; +declare const y: number | null; +asValid(x, n => n >= 0); // OK +asValid(y, n => n >= 0); // Should error + +function tryAt(values: T[], index: number): T | undefined { + return values[index]; +} + +declare const a: number[]; +declare const b: (number | undefined)[]; +tryAt(a, 0); // OK +tryAt(b, 0); // Should error + + +//// [negatedRepresentativeExamples.js] +"use strict"; +// https://github.com/Microsoft/TypeScript/issues/7993 +ignore(readFileSync()); // OK +ignore(readFileAsync()); // Should error +function foo() { } +map([1, 2, 3], n => n + 1); // OK +map([1, 2, 3], foo); // Should error +function asValid(value, isValid) { + return isValid(value) ? value : null; +} +asValid(x, n => n >= 0); // OK +asValid(y, n => n >= 0); // Should error +function tryAt(values, index) { + return values[index]; +} +tryAt(a, 0); // OK +tryAt(b, 0); // Should error diff --git a/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.symbols b/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.symbols new file mode 100644 index 0000000000000..6fcde145646e5 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.symbols @@ -0,0 +1,112 @@ +//// [tests/cases/conformance/types/negated/negatedRepresentativeExamples.ts] //// + +=== negatedRepresentativeExamples.ts === +// https://github.com/Microsoft/TypeScript/issues/7993 + +declare function ignore)>(value: T): void; +>ignore : Symbol(ignore, Decl(negatedRepresentativeExamples.ts, 0, 0)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 2, 24)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +>value : Symbol(value, Decl(negatedRepresentativeExamples.ts, 2, 63)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 2, 24)) + +declare function readFileAsync(): Promise; +>readFileAsync : Symbol(readFileAsync, Decl(negatedRepresentativeExamples.ts, 2, 79)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) + +declare function readFileSync(): string; +>readFileSync : Symbol(readFileSync, Decl(negatedRepresentativeExamples.ts, 3, 50)) + +ignore(readFileSync()); // OK +>ignore : Symbol(ignore, Decl(negatedRepresentativeExamples.ts, 0, 0)) +>readFileSync : Symbol(readFileSync, Decl(negatedRepresentativeExamples.ts, 3, 50)) + +ignore(readFileAsync()); // Should error +>ignore : Symbol(ignore, Decl(negatedRepresentativeExamples.ts, 0, 0)) +>readFileAsync : Symbol(readFileAsync, Decl(negatedRepresentativeExamples.ts, 2, 79)) + +declare function map(values: T[], map: (value: T) => U) : U[]; // validate map callback doesn't return void +>map : Symbol(map, Decl(negatedRepresentativeExamples.ts, 6, 24)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 8, 21)) +>U : Symbol(U, Decl(negatedRepresentativeExamples.ts, 8, 23)) +>values : Symbol(values, Decl(negatedRepresentativeExamples.ts, 8, 44)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 8, 21)) +>map : Symbol(map, Decl(negatedRepresentativeExamples.ts, 8, 56)) +>value : Symbol(value, Decl(negatedRepresentativeExamples.ts, 8, 63)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 8, 21)) +>U : Symbol(U, Decl(negatedRepresentativeExamples.ts, 8, 23)) +>U : Symbol(U, Decl(negatedRepresentativeExamples.ts, 8, 23)) + +function foo() {} +>foo : Symbol(foo, Decl(negatedRepresentativeExamples.ts, 8, 85)) + +map([1, 2, 3], n => n + 1); // OK +>map : Symbol(map, Decl(negatedRepresentativeExamples.ts, 6, 24)) +>n : Symbol(n, Decl(negatedRepresentativeExamples.ts, 12, 14)) +>n : Symbol(n, Decl(negatedRepresentativeExamples.ts, 12, 14)) + +map([1, 2, 3], foo); // Should error +>map : Symbol(map, Decl(negatedRepresentativeExamples.ts, 6, 24)) +>foo : Symbol(foo, Decl(negatedRepresentativeExamples.ts, 8, 85)) + +function asValid(value: T, isValid: (value: T) => boolean) : T | null { +>asValid : Symbol(asValid, Decl(negatedRepresentativeExamples.ts, 13, 20)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 15, 17)) +>value : Symbol(value, Decl(negatedRepresentativeExamples.ts, 15, 37)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 15, 17)) +>isValid : Symbol(isValid, Decl(negatedRepresentativeExamples.ts, 15, 46)) +>value : Symbol(value, Decl(negatedRepresentativeExamples.ts, 15, 57)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 15, 17)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 15, 17)) + + return isValid(value) ? value : null; +>isValid : Symbol(isValid, Decl(negatedRepresentativeExamples.ts, 15, 46)) +>value : Symbol(value, Decl(negatedRepresentativeExamples.ts, 15, 37)) +>value : Symbol(value, Decl(negatedRepresentativeExamples.ts, 15, 37)) +} + +declare const x: number; +>x : Symbol(x, Decl(negatedRepresentativeExamples.ts, 19, 13)) + +declare const y: number | null; +>y : Symbol(y, Decl(negatedRepresentativeExamples.ts, 20, 13)) + +asValid(x, n => n >= 0); // OK +>asValid : Symbol(asValid, Decl(negatedRepresentativeExamples.ts, 13, 20)) +>x : Symbol(x, Decl(negatedRepresentativeExamples.ts, 19, 13)) +>n : Symbol(n, Decl(negatedRepresentativeExamples.ts, 21, 10)) +>n : Symbol(n, Decl(negatedRepresentativeExamples.ts, 21, 10)) + +asValid(y, n => n >= 0); // Should error +>asValid : Symbol(asValid, Decl(negatedRepresentativeExamples.ts, 13, 20)) +>y : Symbol(y, Decl(negatedRepresentativeExamples.ts, 20, 13)) +>n : Symbol(n, Decl(negatedRepresentativeExamples.ts, 22, 10)) +>n : Symbol(n, Decl(negatedRepresentativeExamples.ts, 22, 10)) + +function tryAt(values: T[], index: number): T | undefined { +>tryAt : Symbol(tryAt, Decl(negatedRepresentativeExamples.ts, 22, 24)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 24, 15)) +>values : Symbol(values, Decl(negatedRepresentativeExamples.ts, 24, 40)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 24, 15)) +>index : Symbol(index, Decl(negatedRepresentativeExamples.ts, 24, 52)) +>T : Symbol(T, Decl(negatedRepresentativeExamples.ts, 24, 15)) + + return values[index]; +>values : Symbol(values, Decl(negatedRepresentativeExamples.ts, 24, 40)) +>index : Symbol(index, Decl(negatedRepresentativeExamples.ts, 24, 52)) +} + +declare const a: number[]; +>a : Symbol(a, Decl(negatedRepresentativeExamples.ts, 28, 13)) + +declare const b: (number | undefined)[]; +>b : Symbol(b, Decl(negatedRepresentativeExamples.ts, 29, 13)) + +tryAt(a, 0); // OK +>tryAt : Symbol(tryAt, Decl(negatedRepresentativeExamples.ts, 22, 24)) +>a : Symbol(a, Decl(negatedRepresentativeExamples.ts, 28, 13)) + +tryAt(b, 0); // Should error +>tryAt : Symbol(tryAt, Decl(negatedRepresentativeExamples.ts, 22, 24)) +>b : Symbol(b, Decl(negatedRepresentativeExamples.ts, 29, 13)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.types b/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.types new file mode 100644 index 0000000000000..b841395ebe61e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedRepresentativeExamples.types @@ -0,0 +1,127 @@ +//// [tests/cases/conformance/types/negated/negatedRepresentativeExamples.ts] //// + +=== negatedRepresentativeExamples.ts === +// https://github.com/Microsoft/TypeScript/issues/7993 + +declare function ignore)>(value: T): void; +>ignore : )>(value: T) => void +>value : T + +declare function readFileAsync(): Promise; +>readFileAsync : () => Promise + +declare function readFileSync(): string; +>readFileSync : () => string + +ignore(readFileSync()); // OK +>ignore(readFileSync()) : void +>ignore : )>(value: T) => void +>readFileSync() : string +>readFileSync : () => string + +ignore(readFileAsync()); // Should error +>ignore(readFileAsync()) : void +>ignore : )>(value: T) => void +>readFileAsync() : Promise +>readFileAsync : () => Promise + +declare function map(values: T[], map: (value: T) => U) : U[]; // validate map callback doesn't return void +>map : (values: T[], map: (value: T) => U) => U[] +>values : T[] +>map : (value: T) => U +>value : T + +function foo() {} +>foo : () => void + +map([1, 2, 3], n => n + 1); // OK +>map([1, 2, 3], n => n + 1) : number[] +>map : (values: T[], map: (value: T) => U) => U[] +>[1, 2, 3] : number[] +>1 : 1 +>2 : 2 +>3 : 3 +>n => n + 1 : (n: number) => number +>n : number +>n + 1 : number +>n : number +>1 : 1 + +map([1, 2, 3], foo); // Should error +>map([1, 2, 3], foo) : (not void)[] +>map : (values: T[], map: (value: T) => U) => U[] +>[1, 2, 3] : number[] +>1 : 1 +>2 : 2 +>3 : 3 +>foo : () => void + +function asValid(value: T, isValid: (value: T) => boolean) : T | null { +>asValid : (value: T, isValid: (value: T) => boolean) => T | null +>value : T +>isValid : (value: T) => boolean +>value : T + + return isValid(value) ? value : null; +>isValid(value) ? value : null : T | null +>isValid(value) : boolean +>isValid : (value: T) => boolean +>value : T +>value : T +} + +declare const x: number; +>x : number + +declare const y: number | null; +>y : number | null + +asValid(x, n => n >= 0); // OK +>asValid(x, n => n >= 0) : number | null +>asValid : (value: T, isValid: (value: T) => boolean) => T | null +>x : number +>n => n >= 0 : (n: number) => boolean +>n : number +>n >= 0 : boolean +>n : number +>0 : 0 + +asValid(y, n => n >= 0); // Should error +>asValid(y, n => n >= 0) : unknown +>asValid : (value: T, isValid: (value: T) => boolean) => T | null +>y : number | null +>n => n >= 0 : (n: not null) => boolean +>n : not null +>n >= 0 : boolean +>n : not null +>0 : 0 + +function tryAt(values: T[], index: number): T | undefined { +>tryAt : (values: T[], index: number) => T | undefined +>values : T[] +>index : number + + return values[index]; +>values[index] : T +>values : T[] +>index : number +} + +declare const a: number[]; +>a : number[] + +declare const b: (number | undefined)[]; +>b : (number | undefined)[] + +tryAt(a, 0); // OK +>tryAt(a, 0) : number | undefined +>tryAt : (values: T[], index: number) => T | undefined +>a : number[] +>0 : 0 + +tryAt(b, 0); // Should error +>tryAt(b, 0) : unknown +>tryAt : (values: T[], index: number) => T | undefined +>b : (number | undefined)[] +>0 : 0 + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.errors.txt new file mode 100644 index 0000000000000..a861e267fa306 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.errors.txt @@ -0,0 +1,16 @@ +negatedTypeAppliesToFalseBranchOfConditional.ts(5,47): error TS2344: Type 'T' does not satisfy the constraint 'number'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. + + +==== negatedTypeAppliesToFalseBranchOfConditional.ts (1 errors) ==== + // https://github.com/Microsoft/TypeScript/issues/26240 + + type OnlyNumber = T; + type ToNumber = + T extends string ? undefined : OnlyNumber; + ~ +!!! error TS2344: Type 'T' does not satisfy the constraint 'number'. +!!! error TS2344: Type 'string | number' is not assignable to type 'number'. +!!! error TS2344: Type 'string' is not assignable to type 'number'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.js b/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.js new file mode 100644 index 0000000000000..ff03b413de8df --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.js @@ -0,0 +1,13 @@ +//// [tests/cases/conformance/types/negated/negatedTypeAppliesToFalseBranchOfConditional.ts] //// + +//// [negatedTypeAppliesToFalseBranchOfConditional.ts] +// https://github.com/Microsoft/TypeScript/issues/26240 + +type OnlyNumber = T; +type ToNumber = + T extends string ? undefined : OnlyNumber; + + +//// [negatedTypeAppliesToFalseBranchOfConditional.js] +"use strict"; +// https://github.com/Microsoft/TypeScript/issues/26240 diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.symbols new file mode 100644 index 0000000000000..7b49c323ec841 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.symbols @@ -0,0 +1,19 @@ +//// [tests/cases/conformance/types/negated/negatedTypeAppliesToFalseBranchOfConditional.ts] //// + +=== negatedTypeAppliesToFalseBranchOfConditional.ts === +// https://github.com/Microsoft/TypeScript/issues/26240 + +type OnlyNumber = T; +>OnlyNumber : Symbol(OnlyNumber, Decl(negatedTypeAppliesToFalseBranchOfConditional.ts, 0, 0)) +>T : Symbol(T, Decl(negatedTypeAppliesToFalseBranchOfConditional.ts, 2, 16)) +>T : Symbol(T, Decl(negatedTypeAppliesToFalseBranchOfConditional.ts, 2, 16)) + +type ToNumber = +>ToNumber : Symbol(ToNumber, Decl(negatedTypeAppliesToFalseBranchOfConditional.ts, 2, 38)) +>T : Symbol(T, Decl(negatedTypeAppliesToFalseBranchOfConditional.ts, 3, 14)) + + T extends string ? undefined : OnlyNumber; +>T : Symbol(T, Decl(negatedTypeAppliesToFalseBranchOfConditional.ts, 3, 14)) +>OnlyNumber : Symbol(OnlyNumber, Decl(negatedTypeAppliesToFalseBranchOfConditional.ts, 0, 0)) +>T : Symbol(T, Decl(negatedTypeAppliesToFalseBranchOfConditional.ts, 3, 14)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.types b/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.types new file mode 100644 index 0000000000000..e8202297833eb --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypeAppliesToFalseBranchOfConditional.types @@ -0,0 +1,13 @@ +//// [tests/cases/conformance/types/negated/negatedTypeAppliesToFalseBranchOfConditional.ts] //// + +=== negatedTypeAppliesToFalseBranchOfConditional.ts === +// https://github.com/Microsoft/TypeScript/issues/26240 + +type OnlyNumber = T; +>OnlyNumber : T + +type ToNumber = +>ToNumber : ToNumber + + T extends string ? undefined : OnlyNumber; + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypes.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypes.errors.txt new file mode 100644 index 0000000000000..4d1651114e293 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypes.errors.txt @@ -0,0 +1,379 @@ +negatedTypes.ts(20,5): error TS2322: Type 'string' is not assignable to type 'not string'. +negatedTypes.ts(21,5): error TS2322: Type 'string' is not assignable to type 'not string'. +negatedTypes.ts(22,5): error TS2322: Type 'Literal' is not assignable to type 'not string'. +negatedTypes.ts(26,5): error TS2322: Type 'unknown' is not assignable to type 'not string'. +negatedTypes.ts(29,5): error TS2322: Type 'not string' is not assignable to type 'string'. + Type 'unknown' is not assignable to type 'string'. +negatedTypes.ts(30,5): error TS2322: Type 'not string' is not assignable to type '"ok"'. + Type 'unknown' is not assignable to type '"ok"'. +negatedTypes.ts(31,5): error TS2322: Type 'not string' is not assignable to type 'Literal'. + Type 'unknown' is not assignable to type 'Literal'. +negatedTypes.ts(32,5): error TS2322: Type 'not string' is not assignable to type 'number'. + Type 'unknown' is not assignable to type 'number'. +negatedTypes.ts(33,5): error TS2322: Type 'not string' is not assignable to type '0'. + Type 'unknown' is not assignable to type '0'. +negatedTypes.ts(34,5): error TS2322: Type 'not string' is not assignable to type 'NumLiteral'. + Type 'unknown' is not assignable to type 'NumLiteral'. +negatedTypes.ts(36,5): error TS2322: Type 'not string' is not assignable to type 'never'. + Type 'unknown' is not assignable to type 'never'. +negatedTypes.ts(49,5): error TS2741: Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; }'. +negatedTypes.ts(51,5): error TS2322: Type 'not { x: any; }' is not assignable to type '{ x: any; }'. + Type 'unknown' is not assignable to type '{ x: any; }'. +negatedTypes.ts(52,5): error TS2322: Type 'not { y: any; }' is not assignable to type '{ x: any; }'. + Type 'unknown' is not assignable to type '{ x: any; }'. +negatedTypes.ts(53,5): error TS2322: Type 'not { x: any; y: any; }' is not assignable to type '{ x: any; }'. + Type 'unknown' is not assignable to type '{ x: any; }'. +negatedTypes.ts(54,5): error TS2322: Type 'not { x: any; } & not { y: any; }' is not assignable to type '{ x: any; }'. +negatedTypes.ts(55,5): error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type '{ x: any; }'. + Type 'unknown' is not assignable to type '{ x: any; }'. +negatedTypes.ts(57,5): error TS2741: Property 'y' is missing in type '{ x: any; }' but required in type '{ y: any; }'. +negatedTypes.ts(59,5): error TS2322: Type 'not { x: any; }' is not assignable to type '{ y: any; }'. + Type 'unknown' is not assignable to type '{ y: any; }'. +negatedTypes.ts(60,5): error TS2322: Type 'not { y: any; }' is not assignable to type '{ y: any; }'. + Type 'unknown' is not assignable to type '{ y: any; }'. +negatedTypes.ts(61,5): error TS2322: Type 'not { x: any; y: any; }' is not assignable to type '{ y: any; }'. + Type 'unknown' is not assignable to type '{ y: any; }'. +negatedTypes.ts(62,5): error TS2322: Type 'not { x: any; } & not { y: any; }' is not assignable to type '{ y: any; }'. +negatedTypes.ts(63,5): error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type '{ y: any; }'. + Type 'unknown' is not assignable to type '{ y: any; }'. +negatedTypes.ts(65,5): error TS2741: Property 'y' is missing in type '{ x: any; }' but required in type '{ x: any; y: any; }'. +negatedTypes.ts(66,5): error TS2741: Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; y: any; }'. +negatedTypes.ts(67,5): error TS2322: Type 'not { x: any; }' is not assignable to type '{ x: any; y: any; }'. + Type 'unknown' is not assignable to type '{ x: any; y: any; }'. +negatedTypes.ts(68,5): error TS2322: Type 'not { y: any; }' is not assignable to type '{ x: any; y: any; }'. + Type 'unknown' is not assignable to type '{ x: any; y: any; }'. +negatedTypes.ts(69,5): error TS2322: Type 'not { x: any; y: any; }' is not assignable to type '{ x: any; y: any; }'. + Type 'unknown' is not assignable to type '{ x: any; y: any; }'. +negatedTypes.ts(70,5): error TS2322: Type 'not { x: any; } & not { y: any; }' is not assignable to type '{ x: any; y: any; }'. +negatedTypes.ts(71,5): error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type '{ x: any; y: any; }'. + Type 'unknown' is not assignable to type '{ x: any; y: any; }'. +negatedTypes.ts(73,5): error TS2322: Type '{ x: any; }' is not assignable to type 'not { x: any; }'. +negatedTypes.ts(74,5): error TS2322: Type '{ y: any; }' is not assignable to type 'not { x: any; }'. +negatedTypes.ts(75,5): error TS2322: Type 'not { y: any; }' is not assignable to type 'not { x: any; }'. + Property 'y' is missing in type '{ x: any; }' but required in type '{ y: any; }'. +negatedTypes.ts(76,5): error TS2322: Type 'not { x: any; y: any; }' is not assignable to type 'not { x: any; }'. + Property 'y' is missing in type '{ x: any; }' but required in type '{ x: any; y: any; }'. +negatedTypes.ts(78,5): error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type 'not { x: any; }'. + Type '{ x: any; }' is not assignable to type '{ x: any; } & { y: any; }'. + Property 'y' is missing in type '{ x: any; }' but required in type '{ y: any; }'. +negatedTypes.ts(80,5): error TS2322: Type '{ x: any; }' is not assignable to type 'not { y: any; }'. +negatedTypes.ts(81,5): error TS2322: Type '{ y: any; }' is not assignable to type 'not { y: any; }'. +negatedTypes.ts(82,5): error TS2322: Type 'not { x: any; }' is not assignable to type 'not { y: any; }'. + Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; }'. +negatedTypes.ts(83,5): error TS2322: Type 'not { x: any; y: any; }' is not assignable to type 'not { y: any; }'. + Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; y: any; }'. +negatedTypes.ts(85,5): error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type 'not { y: any; }'. + Type '{ y: any; }' is not assignable to type '{ x: any; } & { y: any; }'. + Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; }'. +negatedTypes.ts(87,5): error TS2322: Type '{ x: any; }' is not assignable to type 'not { x: any; y: any; }'. +negatedTypes.ts(88,5): error TS2322: Type '{ y: any; }' is not assignable to type 'not { x: any; y: any; }'. +negatedTypes.ts(89,5): error TS2322: Type '{ x: any; y: any; }' is not assignable to type 'not { x: any; y: any; }'. +negatedTypes.ts(95,5): error TS2322: Type '{ x: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type '{ x: any; }' is not assignable to type 'not { x: any; }'. +negatedTypes.ts(96,5): error TS2322: Type '{ y: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type '{ y: any; }' is not assignable to type 'not { x: any; }'. +negatedTypes.ts(97,5): error TS2322: Type '{ x: any; y: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type '{ x: any; y: any; }' is not assignable to type 'not { x: any; }'. +negatedTypes.ts(98,5): error TS2322: Type 'not { x: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type 'unknown' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type 'unknown' is not assignable to type 'not { x: any; }'. + Type 'not { x: any; }' is not assignable to type 'not { y: any; }'. + Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; }'. +negatedTypes.ts(99,5): error TS2322: Type 'not { y: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type 'unknown' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type 'unknown' is not assignable to type 'not { x: any; }'. + Type 'not { y: any; }' is not assignable to type 'not { x: any; }'. + Property 'y' is missing in type '{ x: any; }' but required in type '{ y: any; }'. +negatedTypes.ts(100,5): error TS2322: Type 'not { x: any; y: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type 'unknown' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type 'unknown' is not assignable to type 'not { x: any; }'. + Type 'not { x: any; y: any; }' is not assignable to type 'not { x: any; }'. + Property 'y' is missing in type '{ x: any; }' but required in type '{ x: any; y: any; }'. +negatedTypes.ts(101,5): error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type 'unknown' is not assignable to type 'not { x: any; } & not { y: any; }'. + Type 'unknown' is not assignable to type 'not { x: any; }'. + Type 'not ({ x: any; } & { y: any; })' is not assignable to type 'not { x: any; }'. + Type '{ x: any; }' is not assignable to type '{ x: any; } & { y: any; }'. + Property 'y' is missing in type '{ x: any; }' but required in type '{ y: any; }'. +negatedTypes.ts(103,5): error TS2322: Type '{ x: any; }' is not assignable to type 'not ({ x: any; } & { y: any; })'. +negatedTypes.ts(104,5): error TS2322: Type '{ y: any; }' is not assignable to type 'not ({ x: any; } & { y: any; })'. +negatedTypes.ts(105,5): error TS2322: Type '{ x: any; y: any; }' is not assignable to type 'not ({ x: any; } & { y: any; })'. + + +==== negatedTypes.ts (53 errors) ==== + enum Literal { + ok = "ok" + } + + enum NumLiteral { + Val + } + + function f1( + notString: not string, + str: string, + strlit: "ok", + strenum: Literal, + num: number, + numlit: 0, + numenum: NumLiteral, + unknownVal: unknown, + neverVal: never + ) { + notString = str; // not ok + ~~~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'not string'. + notString = strlit; // not ok + ~~~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'not string'. + notString = strenum; // not ok + ~~~~~~~~~ +!!! error TS2322: Type 'Literal' is not assignable to type 'not string'. + notString = num; // ok + notString = numlit; // ok + notString = numenum; // ok + notString = unknownVal; // not ok (unknown is all values, includes string) + ~~~~~~~~~ +!!! error TS2322: Type 'unknown' is not assignable to type 'not string'. + notString = neverVal; // ok (never is empty set of types, doesn't include string) + + str = notString; // not ok + ~~~ +!!! error TS2322: Type 'not string' is not assignable to type 'string'. +!!! error TS2322: Type 'unknown' is not assignable to type 'string'. + strlit = notString; // not ok + ~~~~~~ +!!! error TS2322: Type 'not string' is not assignable to type '"ok"'. +!!! error TS2322: Type 'unknown' is not assignable to type '"ok"'. + strenum = notString; // not ok + ~~~~~~~ +!!! error TS2322: Type 'not string' is not assignable to type 'Literal'. +!!! error TS2322: Type 'unknown' is not assignable to type 'Literal'. + num = notString; // not ok + ~~~ +!!! error TS2322: Type 'not string' is not assignable to type 'number'. +!!! error TS2322: Type 'unknown' is not assignable to type 'number'. + numlit = notString; // not ok + ~~~~~~ +!!! error TS2322: Type 'not string' is not assignable to type '0'. +!!! error TS2322: Type 'unknown' is not assignable to type '0'. + numenum = notString; // not ok + ~~~~~~~ +!!! error TS2322: Type 'not string' is not assignable to type 'NumLiteral'. +!!! error TS2322: Type 'unknown' is not assignable to type 'NumLiteral'. + unknownVal = notString; // ok + neverVal = notString; // not ok + ~~~~~~~~ +!!! error TS2322: Type 'not string' is not assignable to type 'never'. +!!! error TS2322: Type 'unknown' is not assignable to type 'never'. + } + + function f2( + x: { x: any }, + y: { y: any }, + xy: { x: any, y: any }, + nx: not typeof x, + ny: not typeof y, + nxy: not typeof xy, + neither: not (typeof x | typeof y), + notBoth: not (typeof x & typeof y) + ) { + x = y; // not ok + ~ +!!! error TS2741: Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; }'. +!!! related TS2728 negatedTypes.ts:40:10: 'x' is declared here. + x = xy; // ok + x = nx; // not ok + ~ +!!! error TS2322: Type 'not { x: any; }' is not assignable to type '{ x: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ x: any; }'. + x = ny; // not ok + ~ +!!! error TS2322: Type 'not { y: any; }' is not assignable to type '{ x: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ x: any; }'. + x = nxy; // not ok + ~ +!!! error TS2322: Type 'not { x: any; y: any; }' is not assignable to type '{ x: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ x: any; }'. + x = neither; // not ok + ~ +!!! error TS2322: Type 'not { x: any; } & not { y: any; }' is not assignable to type '{ x: any; }'. + x = notBoth; // not ok + ~ +!!! error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type '{ x: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ x: any; }'. + + y = x; // not ok + ~ +!!! error TS2741: Property 'y' is missing in type '{ x: any; }' but required in type '{ y: any; }'. +!!! related TS2728 negatedTypes.ts:41:10: 'y' is declared here. + y = xy; // ok + y = nx; // not ok + ~ +!!! error TS2322: Type 'not { x: any; }' is not assignable to type '{ y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ y: any; }'. + y = ny; // not ok + ~ +!!! error TS2322: Type 'not { y: any; }' is not assignable to type '{ y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ y: any; }'. + y = nxy; // not ok + ~ +!!! error TS2322: Type 'not { x: any; y: any; }' is not assignable to type '{ y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ y: any; }'. + y = neither; // not ok + ~ +!!! error TS2322: Type 'not { x: any; } & not { y: any; }' is not assignable to type '{ y: any; }'. + y = notBoth; // not ok + ~ +!!! error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type '{ y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ y: any; }'. + + xy = x; // not ok + ~~ +!!! error TS2741: Property 'y' is missing in type '{ x: any; }' but required in type '{ x: any; y: any; }'. +!!! related TS2728 negatedTypes.ts:42:19: 'y' is declared here. + xy = y; // not ok + ~~ +!!! error TS2741: Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; y: any; }'. +!!! related TS2728 negatedTypes.ts:42:11: 'x' is declared here. + xy = nx; // not ok + ~~ +!!! error TS2322: Type 'not { x: any; }' is not assignable to type '{ x: any; y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ x: any; y: any; }'. + xy = ny; // not ok + ~~ +!!! error TS2322: Type 'not { y: any; }' is not assignable to type '{ x: any; y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ x: any; y: any; }'. + xy = nxy; // not ok + ~~ +!!! error TS2322: Type 'not { x: any; y: any; }' is not assignable to type '{ x: any; y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ x: any; y: any; }'. + xy = neither; // not ok + ~~ +!!! error TS2322: Type 'not { x: any; } & not { y: any; }' is not assignable to type '{ x: any; y: any; }'. + xy = notBoth; // not ok + ~~ +!!! error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type '{ x: any; y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type '{ x: any; y: any; }'. + + nx = x; // not ok + ~~ +!!! error TS2322: Type '{ x: any; }' is not assignable to type 'not { x: any; }'. + nx = y; // not ok + ~~ +!!! error TS2322: Type '{ y: any; }' is not assignable to type 'not { x: any; }'. + nx = ny; // not ok + ~~ +!!! error TS2322: Type 'not { y: any; }' is not assignable to type 'not { x: any; }'. +!!! error TS2322: Property 'y' is missing in type '{ x: any; }' but required in type '{ y: any; }'. +!!! related TS2728 negatedTypes.ts:41:10: 'y' is declared here. + nx = nxy; // not ok + ~~ +!!! error TS2322: Type 'not { x: any; y: any; }' is not assignable to type 'not { x: any; }'. +!!! error TS2322: Property 'y' is missing in type '{ x: any; }' but required in type '{ x: any; y: any; }'. +!!! related TS2728 negatedTypes.ts:42:19: 'y' is declared here. + nx = neither; // ok + nx = notBoth; // not ok + ~~ +!!! error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type 'not { x: any; }'. +!!! error TS2322: Type '{ x: any; }' is not assignable to type '{ x: any; } & { y: any; }'. +!!! error TS2322: Property 'y' is missing in type '{ x: any; }' but required in type '{ y: any; }'. +!!! related TS2728 negatedTypes.ts:41:10: 'y' is declared here. + + ny = x; // not ok + ~~ +!!! error TS2322: Type '{ x: any; }' is not assignable to type 'not { y: any; }'. + ny = y; // not ok + ~~ +!!! error TS2322: Type '{ y: any; }' is not assignable to type 'not { y: any; }'. + ny = nx; // not ok + ~~ +!!! error TS2322: Type 'not { x: any; }' is not assignable to type 'not { y: any; }'. +!!! error TS2322: Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; }'. +!!! related TS2728 negatedTypes.ts:40:10: 'x' is declared here. + ny = nxy; // not ok + ~~ +!!! error TS2322: Type 'not { x: any; y: any; }' is not assignable to type 'not { y: any; }'. +!!! error TS2322: Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; y: any; }'. +!!! related TS2728 negatedTypes.ts:42:11: 'x' is declared here. + ny = neither; // ok + ny = notBoth; // not ok + ~~ +!!! error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type 'not { y: any; }'. +!!! error TS2322: Type '{ y: any; }' is not assignable to type '{ x: any; } & { y: any; }'. +!!! error TS2322: Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; }'. +!!! related TS2728 negatedTypes.ts:40:10: 'x' is declared here. + + nxy = x; // not ok + ~~~ +!!! error TS2322: Type '{ x: any; }' is not assignable to type 'not { x: any; y: any; }'. + nxy = y; // not ok + ~~~ +!!! error TS2322: Type '{ y: any; }' is not assignable to type 'not { x: any; y: any; }'. + nxy = xy; // not ok + ~~~ +!!! error TS2322: Type '{ x: any; y: any; }' is not assignable to type 'not { x: any; y: any; }'. + nxy = nx; // ok + nxy = ny; // ok + nxy = neither; // ok + nxy = notBoth; // ok + + neither = x; // not ok + ~~~~~~~ +!!! error TS2322: Type '{ x: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type '{ x: any; }' is not assignable to type 'not { x: any; }'. + neither = y; // not ok + ~~~~~~~ +!!! error TS2322: Type '{ y: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type '{ y: any; }' is not assignable to type 'not { x: any; }'. + neither = xy; // not ok + ~~~~~~~ +!!! error TS2322: Type '{ x: any; y: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type '{ x: any; y: any; }' is not assignable to type 'not { x: any; }'. + neither = nx; // not ok + ~~~~~~~ +!!! error TS2322: Type 'not { x: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type 'not { x: any; }'. +!!! error TS2322: Type 'not { x: any; }' is not assignable to type 'not { y: any; }'. +!!! error TS2322: Property 'x' is missing in type '{ y: any; }' but required in type '{ x: any; }'. +!!! related TS2728 negatedTypes.ts:40:10: 'x' is declared here. + neither = ny; // not ok + ~~~~~~~ +!!! error TS2322: Type 'not { y: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type 'not { x: any; }'. +!!! error TS2322: Type 'not { y: any; }' is not assignable to type 'not { x: any; }'. +!!! error TS2322: Property 'y' is missing in type '{ x: any; }' but required in type '{ y: any; }'. +!!! related TS2728 negatedTypes.ts:41:10: 'y' is declared here. + neither = nxy; // not ok + ~~~~~~~ +!!! error TS2322: Type 'not { x: any; y: any; }' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type 'not { x: any; }'. +!!! error TS2322: Type 'not { x: any; y: any; }' is not assignable to type 'not { x: any; }'. +!!! error TS2322: Property 'y' is missing in type '{ x: any; }' but required in type '{ x: any; y: any; }'. +!!! related TS2728 negatedTypes.ts:42:19: 'y' is declared here. + neither = notBoth; // not ok + ~~~~~~~ +!!! error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type 'not { x: any; } & not { y: any; }'. +!!! error TS2322: Type 'unknown' is not assignable to type 'not { x: any; }'. +!!! error TS2322: Type 'not ({ x: any; } & { y: any; })' is not assignable to type 'not { x: any; }'. +!!! error TS2322: Type '{ x: any; }' is not assignable to type '{ x: any; } & { y: any; }'. +!!! error TS2322: Property 'y' is missing in type '{ x: any; }' but required in type '{ y: any; }'. +!!! related TS2728 negatedTypes.ts:41:10: 'y' is declared here. + + notBoth = x; // not ok + ~~~~~~~ +!!! error TS2322: Type '{ x: any; }' is not assignable to type 'not ({ x: any; } & { y: any; })'. + notBoth = y; // not ok + ~~~~~~~ +!!! error TS2322: Type '{ y: any; }' is not assignable to type 'not ({ x: any; } & { y: any; })'. + notBoth = xy; // not ok + ~~~~~~~ +!!! error TS2322: Type '{ x: any; y: any; }' is not assignable to type 'not ({ x: any; } & { y: any; })'. + notBoth = nx; // ok + notBoth = ny; // ok + notBoth = neither; // ok + } \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypes.js b/tsc/testdata/baselines/reference/conformance/negatedTypes.js new file mode 100644 index 0000000000000..d6923831fd9f2 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypes.js @@ -0,0 +1,196 @@ +//// [tests/cases/conformance/types/negated/negatedTypes.ts] //// + +//// [negatedTypes.ts] +enum Literal { + ok = "ok" +} + +enum NumLiteral { + Val +} + +function f1( + notString: not string, + str: string, + strlit: "ok", + strenum: Literal, + num: number, + numlit: 0, + numenum: NumLiteral, + unknownVal: unknown, + neverVal: never +) { + notString = str; // not ok + notString = strlit; // not ok + notString = strenum; // not ok + notString = num; // ok + notString = numlit; // ok + notString = numenum; // ok + notString = unknownVal; // not ok (unknown is all values, includes string) + notString = neverVal; // ok (never is empty set of types, doesn't include string) + + str = notString; // not ok + strlit = notString; // not ok + strenum = notString; // not ok + num = notString; // not ok + numlit = notString; // not ok + numenum = notString; // not ok + unknownVal = notString; // ok + neverVal = notString; // not ok +} + +function f2( + x: { x: any }, + y: { y: any }, + xy: { x: any, y: any }, + nx: not typeof x, + ny: not typeof y, + nxy: not typeof xy, + neither: not (typeof x | typeof y), + notBoth: not (typeof x & typeof y) +) { + x = y; // not ok + x = xy; // ok + x = nx; // not ok + x = ny; // not ok + x = nxy; // not ok + x = neither; // not ok + x = notBoth; // not ok + + y = x; // not ok + y = xy; // ok + y = nx; // not ok + y = ny; // not ok + y = nxy; // not ok + y = neither; // not ok + y = notBoth; // not ok + + xy = x; // not ok + xy = y; // not ok + xy = nx; // not ok + xy = ny; // not ok + xy = nxy; // not ok + xy = neither; // not ok + xy = notBoth; // not ok + + nx = x; // not ok + nx = y; // not ok + nx = ny; // not ok + nx = nxy; // not ok + nx = neither; // ok + nx = notBoth; // not ok + + ny = x; // not ok + ny = y; // not ok + ny = nx; // not ok + ny = nxy; // not ok + ny = neither; // ok + ny = notBoth; // not ok + + nxy = x; // not ok + nxy = y; // not ok + nxy = xy; // not ok + nxy = nx; // ok + nxy = ny; // ok + nxy = neither; // ok + nxy = notBoth; // ok + + neither = x; // not ok + neither = y; // not ok + neither = xy; // not ok + neither = nx; // not ok + neither = ny; // not ok + neither = nxy; // not ok + neither = notBoth; // not ok + + notBoth = x; // not ok + notBoth = y; // not ok + notBoth = xy; // not ok + notBoth = nx; // ok + notBoth = ny; // ok + notBoth = neither; // ok +} + +//// [negatedTypes.js] +"use strict"; +var Literal; +(function (Literal) { + Literal["ok"] = "ok"; +})(Literal || (Literal = {})); +var NumLiteral; +(function (NumLiteral) { + NumLiteral[NumLiteral["Val"] = 0] = "Val"; +})(NumLiteral || (NumLiteral = {})); +function f1(notString, str, strlit, strenum, num, numlit, numenum, unknownVal, neverVal) { + notString = str; // not ok + notString = strlit; // not ok + notString = strenum; // not ok + notString = num; // ok + notString = numlit; // ok + notString = numenum; // ok + notString = unknownVal; // not ok (unknown is all values, includes string) + notString = neverVal; // ok (never is empty set of types, doesn't include string) + str = notString; // not ok + strlit = notString; // not ok + strenum = notString; // not ok + num = notString; // not ok + numlit = notString; // not ok + numenum = notString; // not ok + unknownVal = notString; // ok + neverVal = notString; // not ok +} +function f2(x, y, xy, nx, ny, nxy, neither, notBoth) { + x = y; // not ok + x = xy; // ok + x = nx; // not ok + x = ny; // not ok + x = nxy; // not ok + x = neither; // not ok + x = notBoth; // not ok + y = x; // not ok + y = xy; // ok + y = nx; // not ok + y = ny; // not ok + y = nxy; // not ok + y = neither; // not ok + y = notBoth; // not ok + xy = x; // not ok + xy = y; // not ok + xy = nx; // not ok + xy = ny; // not ok + xy = nxy; // not ok + xy = neither; // not ok + xy = notBoth; // not ok + nx = x; // not ok + nx = y; // not ok + nx = ny; // not ok + nx = nxy; // not ok + nx = neither; // ok + nx = notBoth; // not ok + ny = x; // not ok + ny = y; // not ok + ny = nx; // not ok + ny = nxy; // not ok + ny = neither; // ok + ny = notBoth; // not ok + nxy = x; // not ok + nxy = y; // not ok + nxy = xy; // not ok + nxy = nx; // ok + nxy = ny; // ok + nxy = neither; // ok + nxy = notBoth; // ok + neither = x; // not ok + neither = y; // not ok + neither = xy; // not ok + neither = nx; // not ok + neither = ny; // not ok + neither = nxy; // not ok + neither = notBoth; // not ok + notBoth = x; // not ok + notBoth = y; // not ok + notBoth = xy; // not ok + notBoth = nx; // ok + notBoth = ny; // ok + notBoth = neither; // ok +} diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypes.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypes.symbols new file mode 100644 index 0000000000000..810575f3fd929 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypes.symbols @@ -0,0 +1,366 @@ +//// [tests/cases/conformance/types/negated/negatedTypes.ts] //// + +=== negatedTypes.ts === +enum Literal { +>Literal : Symbol(Literal, Decl(negatedTypes.ts, 0, 0)) + + ok = "ok" +>ok : Symbol(Literal.ok, Decl(negatedTypes.ts, 0, 14)) +} + +enum NumLiteral { +>NumLiteral : Symbol(NumLiteral, Decl(negatedTypes.ts, 2, 1)) + + Val +>Val : Symbol(NumLiteral.Val, Decl(negatedTypes.ts, 4, 17)) +} + +function f1( +>f1 : Symbol(f1, Decl(negatedTypes.ts, 6, 1)) + + notString: not string, +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) + + str: string, +>str : Symbol(str, Decl(negatedTypes.ts, 9, 26)) + + strlit: "ok", +>strlit : Symbol(strlit, Decl(negatedTypes.ts, 10, 16)) + + strenum: Literal, +>strenum : Symbol(strenum, Decl(negatedTypes.ts, 11, 17)) +>Literal : Symbol(Literal, Decl(negatedTypes.ts, 0, 0)) + + num: number, +>num : Symbol(num, Decl(negatedTypes.ts, 12, 21)) + + numlit: 0, +>numlit : Symbol(numlit, Decl(negatedTypes.ts, 13, 16)) + + numenum: NumLiteral, +>numenum : Symbol(numenum, Decl(negatedTypes.ts, 14, 14)) +>NumLiteral : Symbol(NumLiteral, Decl(negatedTypes.ts, 2, 1)) + + unknownVal: unknown, +>unknownVal : Symbol(unknownVal, Decl(negatedTypes.ts, 15, 24)) + + neverVal: never +>neverVal : Symbol(neverVal, Decl(negatedTypes.ts, 16, 24)) + +) { + notString = str; // not ok +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) +>str : Symbol(str, Decl(negatedTypes.ts, 9, 26)) + + notString = strlit; // not ok +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) +>strlit : Symbol(strlit, Decl(negatedTypes.ts, 10, 16)) + + notString = strenum; // not ok +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) +>strenum : Symbol(strenum, Decl(negatedTypes.ts, 11, 17)) + + notString = num; // ok +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) +>num : Symbol(num, Decl(negatedTypes.ts, 12, 21)) + + notString = numlit; // ok +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) +>numlit : Symbol(numlit, Decl(negatedTypes.ts, 13, 16)) + + notString = numenum; // ok +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) +>numenum : Symbol(numenum, Decl(negatedTypes.ts, 14, 14)) + + notString = unknownVal; // not ok (unknown is all values, includes string) +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) +>unknownVal : Symbol(unknownVal, Decl(negatedTypes.ts, 15, 24)) + + notString = neverVal; // ok (never is empty set of types, doesn't include string) +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) +>neverVal : Symbol(neverVal, Decl(negatedTypes.ts, 16, 24)) + + str = notString; // not ok +>str : Symbol(str, Decl(negatedTypes.ts, 9, 26)) +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) + + strlit = notString; // not ok +>strlit : Symbol(strlit, Decl(negatedTypes.ts, 10, 16)) +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) + + strenum = notString; // not ok +>strenum : Symbol(strenum, Decl(negatedTypes.ts, 11, 17)) +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) + + num = notString; // not ok +>num : Symbol(num, Decl(negatedTypes.ts, 12, 21)) +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) + + numlit = notString; // not ok +>numlit : Symbol(numlit, Decl(negatedTypes.ts, 13, 16)) +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) + + numenum = notString; // not ok +>numenum : Symbol(numenum, Decl(negatedTypes.ts, 14, 14)) +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) + + unknownVal = notString; // ok +>unknownVal : Symbol(unknownVal, Decl(negatedTypes.ts, 15, 24)) +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) + + neverVal = notString; // not ok +>neverVal : Symbol(neverVal, Decl(negatedTypes.ts, 16, 24)) +>notString : Symbol(notString, Decl(negatedTypes.ts, 8, 12)) +} + +function f2( +>f2 : Symbol(f2, Decl(negatedTypes.ts, 36, 1)) + + x: { x: any }, +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) +>x : Symbol(x, Decl(negatedTypes.ts, 39, 8)) + + y: { y: any }, +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) +>y : Symbol(y, Decl(negatedTypes.ts, 40, 8)) + + xy: { x: any, y: any }, +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) +>x : Symbol(x, Decl(negatedTypes.ts, 41, 9)) +>y : Symbol(y, Decl(negatedTypes.ts, 41, 17)) + + nx: not typeof x, +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) + + ny: not typeof y, +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) + + nxy: not typeof xy, +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) + + neither: not (typeof x | typeof y), +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) + + notBoth: not (typeof x & typeof y) +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) + +) { + x = y; // not ok +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) + + x = xy; // ok +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) + + x = nx; // not ok +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) + + x = ny; // not ok +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) + + x = nxy; // not ok +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) + + x = neither; // not ok +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) + + x = notBoth; // not ok +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) + + y = x; // not ok +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) + + y = xy; // ok +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) + + y = nx; // not ok +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) + + y = ny; // not ok +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) + + y = nxy; // not ok +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) + + y = neither; // not ok +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) + + y = notBoth; // not ok +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) + + xy = x; // not ok +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) + + xy = y; // not ok +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) + + xy = nx; // not ok +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) + + xy = ny; // not ok +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) + + xy = nxy; // not ok +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) + + xy = neither; // not ok +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) + + xy = notBoth; // not ok +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) + + nx = x; // not ok +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) + + nx = y; // not ok +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) + + nx = ny; // not ok +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) + + nx = nxy; // not ok +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) + + nx = neither; // ok +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) + + nx = notBoth; // not ok +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) + + ny = x; // not ok +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) + + ny = y; // not ok +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) + + ny = nx; // not ok +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) + + ny = nxy; // not ok +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) + + ny = neither; // ok +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) + + ny = notBoth; // not ok +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) + + nxy = x; // not ok +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) + + nxy = y; // not ok +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) + + nxy = xy; // not ok +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) + + nxy = nx; // ok +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) + + nxy = ny; // ok +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) + + nxy = neither; // ok +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) + + nxy = notBoth; // ok +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) + + neither = x; // not ok +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) + + neither = y; // not ok +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) + + neither = xy; // not ok +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) + + neither = nx; // not ok +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) + + neither = ny; // not ok +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) + + neither = nxy; // not ok +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) +>nxy : Symbol(nxy, Decl(negatedTypes.ts, 43, 21)) + + neither = notBoth; // not ok +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) + + notBoth = x; // not ok +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) +>x : Symbol(x, Decl(negatedTypes.ts, 38, 12)) + + notBoth = y; // not ok +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) +>y : Symbol(y, Decl(negatedTypes.ts, 39, 18)) + + notBoth = xy; // not ok +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) +>xy : Symbol(xy, Decl(negatedTypes.ts, 40, 18)) + + notBoth = nx; // ok +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) +>nx : Symbol(nx, Decl(negatedTypes.ts, 41, 27)) + + notBoth = ny; // ok +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) +>ny : Symbol(ny, Decl(negatedTypes.ts, 42, 21)) + + notBoth = neither; // ok +>notBoth : Symbol(notBoth, Decl(negatedTypes.ts, 45, 39)) +>neither : Symbol(neither, Decl(negatedTypes.ts, 44, 23)) +} diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypes.types b/tsc/testdata/baselines/reference/conformance/negatedTypes.types new file mode 100644 index 0000000000000..3cda345550e8e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypes.types @@ -0,0 +1,434 @@ +//// [tests/cases/conformance/types/negated/negatedTypes.ts] //// + +=== negatedTypes.ts === +enum Literal { +>Literal : Literal + + ok = "ok" +>ok : Literal.ok +>"ok" : "ok" +} + +enum NumLiteral { +>NumLiteral : NumLiteral + + Val +>Val : NumLiteral.Val +} + +function f1( +>f1 : (notString: not string, str: string, strlit: "ok", strenum: Literal, num: number, numlit: 0, numenum: NumLiteral, unknownVal: unknown, neverVal: never) => void + + notString: not string, +>notString : not string + + str: string, +>str : string + + strlit: "ok", +>strlit : "ok" + + strenum: Literal, +>strenum : Literal + + num: number, +>num : number + + numlit: 0, +>numlit : 0 + + numenum: NumLiteral, +>numenum : NumLiteral + + unknownVal: unknown, +>unknownVal : unknown + + neverVal: never +>neverVal : never + +) { + notString = str; // not ok +>notString = str : string +>notString : not string +>str : string + + notString = strlit; // not ok +>notString = strlit : "ok" +>notString : not string +>strlit : "ok" + + notString = strenum; // not ok +>notString = strenum : Literal +>notString : not string +>strenum : Literal + + notString = num; // ok +>notString = num : number +>notString : not string +>num : number + + notString = numlit; // ok +>notString = numlit : 0 +>notString : not string +>numlit : 0 + + notString = numenum; // ok +>notString = numenum : NumLiteral +>notString : not string +>numenum : NumLiteral + + notString = unknownVal; // not ok (unknown is all values, includes string) +>notString = unknownVal : unknown +>notString : not string +>unknownVal : unknown + + notString = neverVal; // ok (never is empty set of types, doesn't include string) +>notString = neverVal : never +>notString : not string +>neverVal : never + + str = notString; // not ok +>str = notString : not string +>str : string +>notString : not string + + strlit = notString; // not ok +>strlit = notString : not string +>strlit : "ok" +>notString : not string + + strenum = notString; // not ok +>strenum = notString : not string +>strenum : Literal +>notString : not string + + num = notString; // not ok +>num = notString : not string +>num : number +>notString : not string + + numlit = notString; // not ok +>numlit = notString : not string +>numlit : 0 +>notString : not string + + numenum = notString; // not ok +>numenum = notString : not string +>numenum : NumLiteral +>notString : not string + + unknownVal = notString; // ok +>unknownVal = notString : not string +>unknownVal : unknown +>notString : not string + + neverVal = notString; // not ok +>neverVal = notString : not string +>neverVal : never +>notString : not string +} + +function f2( +>f2 : (x: { x: any; }, y: { y: any; }, xy: { x: any; y: any; }, nx: not typeof x, ny: not typeof y, nxy: not typeof xy, neither: not (typeof x | typeof y), notBoth: not (typeof x & typeof y)) => void + + x: { x: any }, +>x : { x: any; } +>x : any + + y: { y: any }, +>y : { y: any; } +>y : any + + xy: { x: any, y: any }, +>xy : { x: any; y: any; } +>x : any +>y : any + + nx: not typeof x, +>nx : not { x: any; } +>x : { x: any; } + + ny: not typeof y, +>ny : not { y: any; } +>y : { y: any; } + + nxy: not typeof xy, +>nxy : not { x: any; y: any; } +>xy : { x: any; y: any; } + + neither: not (typeof x | typeof y), +>neither : not { x: any; } & not { y: any; } +>x : { x: any; } +>y : { y: any; } + + notBoth: not (typeof x & typeof y) +>notBoth : not ({ x: any; } & { y: any; }) +>x : { x: any; } +>y : { y: any; } + +) { + x = y; // not ok +>x = y : { y: any; } +>x : { x: any; } +>y : { y: any; } + + x = xy; // ok +>x = xy : { x: any; y: any; } +>x : { x: any; } +>xy : { x: any; y: any; } + + x = nx; // not ok +>x = nx : not { x: any; } +>x : { x: any; } +>nx : not { x: any; } + + x = ny; // not ok +>x = ny : not { y: any; } +>x : { x: any; } +>ny : not { y: any; } + + x = nxy; // not ok +>x = nxy : not { x: any; y: any; } +>x : { x: any; } +>nxy : not { x: any; y: any; } + + x = neither; // not ok +>x = neither : not { x: any; } & not { y: any; } +>x : { x: any; } +>neither : not { x: any; } & not { y: any; } + + x = notBoth; // not ok +>x = notBoth : not ({ x: any; } & { y: any; }) +>x : { x: any; } +>notBoth : not ({ x: any; } & { y: any; }) + + y = x; // not ok +>y = x : { x: any; } +>y : { y: any; } +>x : { x: any; } + + y = xy; // ok +>y = xy : { x: any; y: any; } +>y : { y: any; } +>xy : { x: any; y: any; } + + y = nx; // not ok +>y = nx : not { x: any; } +>y : { y: any; } +>nx : not { x: any; } + + y = ny; // not ok +>y = ny : not { y: any; } +>y : { y: any; } +>ny : not { y: any; } + + y = nxy; // not ok +>y = nxy : not { x: any; y: any; } +>y : { y: any; } +>nxy : not { x: any; y: any; } + + y = neither; // not ok +>y = neither : not { x: any; } & not { y: any; } +>y : { y: any; } +>neither : not { x: any; } & not { y: any; } + + y = notBoth; // not ok +>y = notBoth : not ({ x: any; } & { y: any; }) +>y : { y: any; } +>notBoth : not ({ x: any; } & { y: any; }) + + xy = x; // not ok +>xy = x : { x: any; } +>xy : { x: any; y: any; } +>x : { x: any; } + + xy = y; // not ok +>xy = y : { y: any; } +>xy : { x: any; y: any; } +>y : { y: any; } + + xy = nx; // not ok +>xy = nx : not { x: any; } +>xy : { x: any; y: any; } +>nx : not { x: any; } + + xy = ny; // not ok +>xy = ny : not { y: any; } +>xy : { x: any; y: any; } +>ny : not { y: any; } + + xy = nxy; // not ok +>xy = nxy : not { x: any; y: any; } +>xy : { x: any; y: any; } +>nxy : not { x: any; y: any; } + + xy = neither; // not ok +>xy = neither : not { x: any; } & not { y: any; } +>xy : { x: any; y: any; } +>neither : not { x: any; } & not { y: any; } + + xy = notBoth; // not ok +>xy = notBoth : not ({ x: any; } & { y: any; }) +>xy : { x: any; y: any; } +>notBoth : not ({ x: any; } & { y: any; }) + + nx = x; // not ok +>nx = x : { x: any; } +>nx : not { x: any; } +>x : { x: any; } + + nx = y; // not ok +>nx = y : { y: any; } +>nx : not { x: any; } +>y : { y: any; } + + nx = ny; // not ok +>nx = ny : not { y: any; } +>nx : not { x: any; } +>ny : not { y: any; } + + nx = nxy; // not ok +>nx = nxy : not { x: any; y: any; } +>nx : not { x: any; } +>nxy : not { x: any; y: any; } + + nx = neither; // ok +>nx = neither : not { x: any; } & not { y: any; } +>nx : not { x: any; } +>neither : not { x: any; } & not { y: any; } + + nx = notBoth; // not ok +>nx = notBoth : not ({ x: any; } & { y: any; }) +>nx : not { x: any; } +>notBoth : not ({ x: any; } & { y: any; }) + + ny = x; // not ok +>ny = x : { x: any; } +>ny : not { y: any; } +>x : { x: any; } + + ny = y; // not ok +>ny = y : { y: any; } +>ny : not { y: any; } +>y : { y: any; } + + ny = nx; // not ok +>ny = nx : not { x: any; } +>ny : not { y: any; } +>nx : not { x: any; } + + ny = nxy; // not ok +>ny = nxy : not { x: any; y: any; } +>ny : not { y: any; } +>nxy : not { x: any; y: any; } + + ny = neither; // ok +>ny = neither : not { x: any; } & not { y: any; } +>ny : not { y: any; } +>neither : not { x: any; } & not { y: any; } + + ny = notBoth; // not ok +>ny = notBoth : not ({ x: any; } & { y: any; }) +>ny : not { y: any; } +>notBoth : not ({ x: any; } & { y: any; }) + + nxy = x; // not ok +>nxy = x : { x: any; } +>nxy : not { x: any; y: any; } +>x : { x: any; } + + nxy = y; // not ok +>nxy = y : { y: any; } +>nxy : not { x: any; y: any; } +>y : { y: any; } + + nxy = xy; // not ok +>nxy = xy : { x: any; y: any; } +>nxy : not { x: any; y: any; } +>xy : { x: any; y: any; } + + nxy = nx; // ok +>nxy = nx : not { x: any; } +>nxy : not { x: any; y: any; } +>nx : not { x: any; } + + nxy = ny; // ok +>nxy = ny : not { y: any; } +>nxy : not { x: any; y: any; } +>ny : not { y: any; } + + nxy = neither; // ok +>nxy = neither : not { x: any; } & not { y: any; } +>nxy : not { x: any; y: any; } +>neither : not { x: any; } & not { y: any; } + + nxy = notBoth; // ok +>nxy = notBoth : not ({ x: any; } & { y: any; }) +>nxy : not { x: any; y: any; } +>notBoth : not ({ x: any; } & { y: any; }) + + neither = x; // not ok +>neither = x : { x: any; } +>neither : not { x: any; } & not { y: any; } +>x : { x: any; } + + neither = y; // not ok +>neither = y : { y: any; } +>neither : not { x: any; } & not { y: any; } +>y : { y: any; } + + neither = xy; // not ok +>neither = xy : { x: any; y: any; } +>neither : not { x: any; } & not { y: any; } +>xy : { x: any; y: any; } + + neither = nx; // not ok +>neither = nx : not { x: any; } +>neither : not { x: any; } & not { y: any; } +>nx : not { x: any; } + + neither = ny; // not ok +>neither = ny : not { y: any; } +>neither : not { x: any; } & not { y: any; } +>ny : not { y: any; } + + neither = nxy; // not ok +>neither = nxy : not { x: any; y: any; } +>neither : not { x: any; } & not { y: any; } +>nxy : not { x: any; y: any; } + + neither = notBoth; // not ok +>neither = notBoth : not ({ x: any; } & { y: any; }) +>neither : not { x: any; } & not { y: any; } +>notBoth : not ({ x: any; } & { y: any; }) + + notBoth = x; // not ok +>notBoth = x : { x: any; } +>notBoth : not ({ x: any; } & { y: any; }) +>x : { x: any; } + + notBoth = y; // not ok +>notBoth = y : { y: any; } +>notBoth : not ({ x: any; } & { y: any; }) +>y : { y: any; } + + notBoth = xy; // not ok +>notBoth = xy : { x: any; y: any; } +>notBoth : not ({ x: any; } & { y: any; }) +>xy : { x: any; y: any; } + + notBoth = nx; // ok +>notBoth = nx : not { x: any; } +>notBoth : not ({ x: any; } & { y: any; }) +>nx : not { x: any; } + + notBoth = ny; // ok +>notBoth = ny : not { y: any; } +>notBoth : not ({ x: any; } & { y: any; }) +>ny : not { y: any; } + + notBoth = neither; // ok +>notBoth = neither : not { x: any; } & not { y: any; } +>notBoth : not ({ x: any; } & { y: any; }) +>neither : not { x: any; } & not { y: any; } +} diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesContravariantInference.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesContravariantInference.symbols new file mode 100644 index 0000000000000..d561df5b07b22 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesContravariantInference.symbols @@ -0,0 +1,100 @@ +//// [tests/cases/conformance/types/negated/negatedTypesContravariantInference.ts] //// + +=== negatedTypesContravariantInference.ts === +// Demonstrates why inference through the `not` operator must be contravariant. +// +// `T` appears only in `not T` positions and receives one candidate from each argument: +// `{ a: number }` and `{ a: number; b: number }`. Note the second is a *subtype* of the +// first. +// +// For the call to be well-typed, both `Box` and `Box` must be assignable to +// `Box`. Since `not` reverses subtyping, `not A <: not T` requires `T <: A`, and +// likewise `T <: B`. So `T` must be a common *subtype* of the two operands, i.e. the more +// specific `{ a: number; b: number }`. Contravariant inference produces exactly this by +// combining candidates with `getCommonSubtype`. +// +// Covariant inference would instead combine them with `getCommonSupertype`, yielding the +// wider `{ a: number }`. That `T` is not assignable back into the `Box` +// parameter (it would require `{ a } <: { a; b }`, which is false), so the call would fail +// and `r.b` would be inaccessible. + +interface Box { value: T; } +>Box : Symbol(Box, Decl(negatedTypesContravariantInference.ts, 0, 0)) +>T : Symbol(T, Decl(negatedTypesContravariantInference.ts, 17, 14)) +>value : Symbol(Box.value, Decl(negatedTypesContravariantInference.ts, 17, 18)) +>T : Symbol(T, Decl(negatedTypesContravariantInference.ts, 17, 14)) + +declare function combine(x: Box, y: Box): T; +>combine : Symbol(combine, Decl(negatedTypesContravariantInference.ts, 17, 30)) +>T : Symbol(T, Decl(negatedTypesContravariantInference.ts, 19, 25)) +>x : Symbol(x, Decl(negatedTypesContravariantInference.ts, 19, 28)) +>Box : Symbol(Box, Decl(negatedTypesContravariantInference.ts, 0, 0)) +>T : Symbol(T, Decl(negatedTypesContravariantInference.ts, 19, 25)) +>y : Symbol(y, Decl(negatedTypesContravariantInference.ts, 19, 42)) +>Box : Symbol(Box, Decl(negatedTypesContravariantInference.ts, 0, 0)) +>T : Symbol(T, Decl(negatedTypesContravariantInference.ts, 19, 25)) +>T : Symbol(T, Decl(negatedTypesContravariantInference.ts, 19, 25)) + +declare const boxNotA: Box; +>boxNotA : Symbol(boxNotA, Decl(negatedTypesContravariantInference.ts, 21, 13)) +>Box : Symbol(Box, Decl(negatedTypesContravariantInference.ts, 0, 0)) +>a : Symbol(a, Decl(negatedTypesContravariantInference.ts, 21, 32)) + +declare const boxNotAB: Box; +>boxNotAB : Symbol(boxNotAB, Decl(negatedTypesContravariantInference.ts, 22, 13)) +>Box : Symbol(Box, Decl(negatedTypesContravariantInference.ts, 0, 0)) +>a : Symbol(a, Decl(negatedTypesContravariantInference.ts, 22, 33)) +>b : Symbol(b, Decl(negatedTypesContravariantInference.ts, 22, 44)) + +// Contravariant inference: T = { a: number; b: number } (the common subtype). +const r = combine(boxNotA, boxNotAB); +>r : Symbol(r, Decl(negatedTypesContravariantInference.ts, 25, 5)) +>combine : Symbol(combine, Decl(negatedTypesContravariantInference.ts, 17, 30)) +>boxNotA : Symbol(boxNotA, Decl(negatedTypesContravariantInference.ts, 21, 13)) +>boxNotAB : Symbol(boxNotAB, Decl(negatedTypesContravariantInference.ts, 22, 13)) + +r.a; // ok +>r.a : Symbol(a, Decl(negatedTypesContravariantInference.ts, 22, 33)) +>r : Symbol(r, Decl(negatedTypesContravariantInference.ts, 25, 5)) +>a : Symbol(a, Decl(negatedTypesContravariantInference.ts, 22, 33)) + +r.b; // ok only because contravariant inference chose the subtype; covariant would pick { a } and error here +>r.b : Symbol(b, Decl(negatedTypesContravariantInference.ts, 22, 44)) +>r : Symbol(r, Decl(negatedTypesContravariantInference.ts, 25, 5)) +>b : Symbol(b, Decl(negatedTypesContravariantInference.ts, 22, 44)) + +// The same effect with plain (non-wrapped) negated parameters. +declare function combineBare(x: not T, y: not T): T; +>combineBare : Symbol(combineBare, Decl(negatedTypesContravariantInference.ts, 28, 4)) +>T : Symbol(T, Decl(negatedTypesContravariantInference.ts, 31, 29)) +>x : Symbol(x, Decl(negatedTypesContravariantInference.ts, 31, 32)) +>T : Symbol(T, Decl(negatedTypesContravariantInference.ts, 31, 29)) +>y : Symbol(y, Decl(negatedTypesContravariantInference.ts, 31, 41)) +>T : Symbol(T, Decl(negatedTypesContravariantInference.ts, 31, 29)) +>T : Symbol(T, Decl(negatedTypesContravariantInference.ts, 31, 29)) + +declare const notA: not { a: number }; +>notA : Symbol(notA, Decl(negatedTypesContravariantInference.ts, 32, 13)) +>a : Symbol(a, Decl(negatedTypesContravariantInference.ts, 32, 25)) + +declare const notAB: not { a: number; b: number }; +>notAB : Symbol(notAB, Decl(negatedTypesContravariantInference.ts, 33, 13)) +>a : Symbol(a, Decl(negatedTypesContravariantInference.ts, 33, 26)) +>b : Symbol(b, Decl(negatedTypesContravariantInference.ts, 33, 37)) + +const r2 = combineBare(notA, notAB); // T = { a: number; b: number } +>r2 : Symbol(r2, Decl(negatedTypesContravariantInference.ts, 35, 5)) +>combineBare : Symbol(combineBare, Decl(negatedTypesContravariantInference.ts, 28, 4)) +>notA : Symbol(notA, Decl(negatedTypesContravariantInference.ts, 32, 13)) +>notAB : Symbol(notAB, Decl(negatedTypesContravariantInference.ts, 33, 13)) + +r2.a; // ok +>r2.a : Symbol(a, Decl(negatedTypesContravariantInference.ts, 33, 26)) +>r2 : Symbol(r2, Decl(negatedTypesContravariantInference.ts, 35, 5)) +>a : Symbol(a, Decl(negatedTypesContravariantInference.ts, 33, 26)) + +r2.b; // ok only with contravariant inference +>r2.b : Symbol(b, Decl(negatedTypesContravariantInference.ts, 33, 37)) +>r2 : Symbol(r2, Decl(negatedTypesContravariantInference.ts, 35, 5)) +>b : Symbol(b, Decl(negatedTypesContravariantInference.ts, 33, 37)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesContravariantInference.types b/tsc/testdata/baselines/reference/conformance/negatedTypesContravariantInference.types new file mode 100644 index 0000000000000..ba96263be0fbc --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesContravariantInference.types @@ -0,0 +1,87 @@ +//// [tests/cases/conformance/types/negated/negatedTypesContravariantInference.ts] //// + +=== negatedTypesContravariantInference.ts === +// Demonstrates why inference through the `not` operator must be contravariant. +// +// `T` appears only in `not T` positions and receives one candidate from each argument: +// `{ a: number }` and `{ a: number; b: number }`. Note the second is a *subtype* of the +// first. +// +// For the call to be well-typed, both `Box` and `Box` must be assignable to +// `Box`. Since `not` reverses subtyping, `not A <: not T` requires `T <: A`, and +// likewise `T <: B`. So `T` must be a common *subtype* of the two operands, i.e. the more +// specific `{ a: number; b: number }`. Contravariant inference produces exactly this by +// combining candidates with `getCommonSubtype`. +// +// Covariant inference would instead combine them with `getCommonSupertype`, yielding the +// wider `{ a: number }`. That `T` is not assignable back into the `Box` +// parameter (it would require `{ a } <: { a; b }`, which is false), so the call would fail +// and `r.b` would be inaccessible. + +interface Box { value: T; } +>value : T + +declare function combine(x: Box, y: Box): T; +>combine : (x: Box, y: Box) => T +>x : Box +>y : Box + +declare const boxNotA: Box; +>boxNotA : Box +>a : number + +declare const boxNotAB: Box; +>boxNotAB : Box +>a : number +>b : number + +// Contravariant inference: T = { a: number; b: number } (the common subtype). +const r = combine(boxNotA, boxNotAB); +>r : { a: number; b: number; } +>combine(boxNotA, boxNotAB) : { a: number; b: number; } +>combine : (x: Box, y: Box) => T +>boxNotA : Box +>boxNotAB : Box + +r.a; // ok +>r.a : number +>r : { a: number; b: number; } +>a : number + +r.b; // ok only because contravariant inference chose the subtype; covariant would pick { a } and error here +>r.b : number +>r : { a: number; b: number; } +>b : number + +// The same effect with plain (non-wrapped) negated parameters. +declare function combineBare(x: not T, y: not T): T; +>combineBare : (x: not T, y: not T) => T +>x : not T +>y : not T + +declare const notA: not { a: number }; +>notA : not { a: number; } +>a : number + +declare const notAB: not { a: number; b: number }; +>notAB : not { a: number; b: number; } +>a : number +>b : number + +const r2 = combineBare(notA, notAB); // T = { a: number; b: number } +>r2 : { a: number; b: number; } +>combineBare(notA, notAB) : { a: number; b: number; } +>combineBare : (x: not T, y: not T) => T +>notA : not { a: number; } +>notAB : not { a: number; b: number; } + +r2.a; // ok +>r2.a : number +>r2 : { a: number; b: number; } +>a : number + +r2.b; // ok only with contravariant inference +>r2.b : number +>r2 : { a: number; b: number; } +>b : number + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlow.js b/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlow.js new file mode 100644 index 0000000000000..d99df343dc340 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlow.js @@ -0,0 +1,36 @@ +//// [tests/cases/conformance/types/negated/negatedTypesControlFlow.ts] //// + +//// [negatedTypesControlFlow.ts] +interface A { type: "a", data: number } +interface B { type: "b", data: string } +interface Unknown { type: string & not ("a"|"b"), data: object } +type ABU = A | B | Unknown; +declare function needsNumber(x: number): void; +declare function needsString(x: string): void; +declare function needsObject(x: object): void; +declare var x: ABU; + +if (x.type === "a") { + let y = x.data; + needsNumber(y); +} +else if (x.type === "b") { + needsString(x.data); +} +else { + needsObject(x.data); +} + + +//// [negatedTypesControlFlow.js] +"use strict"; +if (x.type === "a") { + let y = x.data; + needsNumber(y); +} +else if (x.type === "b") { + needsString(x.data); +} +else { + needsObject(x.data); +} diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlow.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlow.symbols new file mode 100644 index 0000000000000..7aa9291a883ab --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlow.symbols @@ -0,0 +1,74 @@ +//// [tests/cases/conformance/types/negated/negatedTypesControlFlow.ts] //// + +=== negatedTypesControlFlow.ts === +interface A { type: "a", data: number } +>A : Symbol(A, Decl(negatedTypesControlFlow.ts, 0, 0)) +>type : Symbol(A.type, Decl(negatedTypesControlFlow.ts, 0, 13)) +>data : Symbol(A.data, Decl(negatedTypesControlFlow.ts, 0, 24)) + +interface B { type: "b", data: string } +>B : Symbol(B, Decl(negatedTypesControlFlow.ts, 0, 39)) +>type : Symbol(B.type, Decl(negatedTypesControlFlow.ts, 1, 13)) +>data : Symbol(B.data, Decl(negatedTypesControlFlow.ts, 1, 24)) + +interface Unknown { type: string & not ("a"|"b"), data: object } +>Unknown : Symbol(Unknown, Decl(negatedTypesControlFlow.ts, 1, 39)) +>type : Symbol(Unknown.type, Decl(negatedTypesControlFlow.ts, 2, 19)) +>data : Symbol(Unknown.data, Decl(negatedTypesControlFlow.ts, 2, 49)) + +type ABU = A | B | Unknown; +>ABU : Symbol(ABU, Decl(negatedTypesControlFlow.ts, 2, 64)) +>A : Symbol(A, Decl(negatedTypesControlFlow.ts, 0, 0)) +>B : Symbol(B, Decl(negatedTypesControlFlow.ts, 0, 39)) +>Unknown : Symbol(Unknown, Decl(negatedTypesControlFlow.ts, 1, 39)) + +declare function needsNumber(x: number): void; +>needsNumber : Symbol(needsNumber, Decl(negatedTypesControlFlow.ts, 3, 27)) +>x : Symbol(x, Decl(negatedTypesControlFlow.ts, 4, 29)) + +declare function needsString(x: string): void; +>needsString : Symbol(needsString, Decl(negatedTypesControlFlow.ts, 4, 46)) +>x : Symbol(x, Decl(negatedTypesControlFlow.ts, 5, 29)) + +declare function needsObject(x: object): void; +>needsObject : Symbol(needsObject, Decl(negatedTypesControlFlow.ts, 5, 46)) +>x : Symbol(x, Decl(negatedTypesControlFlow.ts, 6, 29)) + +declare var x: ABU; +>x : Symbol(x, Decl(negatedTypesControlFlow.ts, 7, 11)) +>ABU : Symbol(ABU, Decl(negatedTypesControlFlow.ts, 2, 64)) + +if (x.type === "a") { +>x.type : Symbol(type, Decl(negatedTypesControlFlow.ts, 0, 13), Decl(negatedTypesControlFlow.ts, 1, 13), Decl(negatedTypesControlFlow.ts, 2, 19)) +>x : Symbol(x, Decl(negatedTypesControlFlow.ts, 7, 11)) +>type : Symbol(type, Decl(negatedTypesControlFlow.ts, 0, 13), Decl(negatedTypesControlFlow.ts, 1, 13), Decl(negatedTypesControlFlow.ts, 2, 19)) + + let y = x.data; +>y : Symbol(y, Decl(negatedTypesControlFlow.ts, 10, 7)) +>x.data : Symbol(A.data, Decl(negatedTypesControlFlow.ts, 0, 24)) +>x : Symbol(x, Decl(negatedTypesControlFlow.ts, 7, 11)) +>data : Symbol(A.data, Decl(negatedTypesControlFlow.ts, 0, 24)) + + needsNumber(y); +>needsNumber : Symbol(needsNumber, Decl(negatedTypesControlFlow.ts, 3, 27)) +>y : Symbol(y, Decl(negatedTypesControlFlow.ts, 10, 7)) +} +else if (x.type === "b") { +>x.type : Symbol(type, Decl(negatedTypesControlFlow.ts, 1, 13), Decl(negatedTypesControlFlow.ts, 2, 19)) +>x : Symbol(x, Decl(negatedTypesControlFlow.ts, 7, 11)) +>type : Symbol(type, Decl(negatedTypesControlFlow.ts, 1, 13), Decl(negatedTypesControlFlow.ts, 2, 19)) + + needsString(x.data); +>needsString : Symbol(needsString, Decl(negatedTypesControlFlow.ts, 4, 46)) +>x.data : Symbol(B.data, Decl(negatedTypesControlFlow.ts, 1, 24)) +>x : Symbol(x, Decl(negatedTypesControlFlow.ts, 7, 11)) +>data : Symbol(B.data, Decl(negatedTypesControlFlow.ts, 1, 24)) +} +else { + needsObject(x.data); +>needsObject : Symbol(needsObject, Decl(negatedTypesControlFlow.ts, 5, 46)) +>x.data : Symbol(Unknown.data, Decl(negatedTypesControlFlow.ts, 2, 49)) +>x : Symbol(x, Decl(negatedTypesControlFlow.ts, 7, 11)) +>data : Symbol(Unknown.data, Decl(negatedTypesControlFlow.ts, 2, 49)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlow.types b/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlow.types new file mode 100644 index 0000000000000..8a5ea7d848d8f --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlow.types @@ -0,0 +1,74 @@ +//// [tests/cases/conformance/types/negated/negatedTypesControlFlow.ts] //// + +=== negatedTypesControlFlow.ts === +interface A { type: "a", data: number } +>type : "a" +>data : number + +interface B { type: "b", data: string } +>type : "b" +>data : string + +interface Unknown { type: string & not ("a"|"b"), data: object } +>type : string & not "a" & not "b" +>data : object + +type ABU = A | B | Unknown; +>ABU : ABU + +declare function needsNumber(x: number): void; +>needsNumber : (x: number) => void +>x : number + +declare function needsString(x: string): void; +>needsString : (x: string) => void +>x : string + +declare function needsObject(x: object): void; +>needsObject : (x: object) => void +>x : object + +declare var x: ABU; +>x : ABU + +if (x.type === "a") { +>x.type === "a" : boolean +>x.type : "a" | "b" | (string & not "a" & not "b") +>x : ABU +>type : "a" | "b" | (string & not "a" & not "b") +>"a" : "a" + + let y = x.data; +>y : number +>x.data : number +>x : A +>data : number + + needsNumber(y); +>needsNumber(y) : void +>needsNumber : (x: number) => void +>y : number +} +else if (x.type === "b") { +>x.type === "b" : boolean +>x.type : "b" | (string & not "a" & not "b") +>x : B | Unknown +>type : "b" | (string & not "a" & not "b") +>"b" : "b" + + needsString(x.data); +>needsString(x.data) : void +>needsString : (x: string) => void +>x.data : string +>x : B +>data : string +} +else { + needsObject(x.data); +>needsObject(x.data) : void +>needsObject : (x: object) => void +>x.data : object +>x : Unknown +>data : object +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlowNarrowing.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlowNarrowing.symbols new file mode 100644 index 0000000000000..29fb5f3748398 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlowNarrowing.symbols @@ -0,0 +1,97 @@ +//// [tests/cases/conformance/types/negated/negatedTypesControlFlowNarrowing.ts] //// + +=== negatedTypesControlFlowNarrowing.ts === +// Control flow narrowing introduces negated types in the false branch of a narrowing check. +// The negation is only retained where it is non-redundant (i.e. the narrowed base type overlaps +// the removed candidate, such as `{}` / `unknown`); for ordinary disjoint unions it reduces away. + +declare function wantsStr(x: string): void; +>wantsStr : Symbol(wantsStr, Decl(negatedTypesControlFlowNarrowing.ts, 0, 0)) +>x : Symbol(x, Decl(negatedTypesControlFlowNarrowing.ts, 4, 26)) + +declare function wantsNotStr(x: not string): void; +>wantsNotStr : Symbol(wantsNotStr, Decl(negatedTypesControlFlowNarrowing.ts, 4, 43)) +>x : Symbol(x, Decl(negatedTypesControlFlowNarrowing.ts, 5, 29)) + +declare function wantsNegatedCallbackResult(cb: () => not string): void; +>wantsNegatedCallbackResult : Symbol(wantsNegatedCallbackResult, Decl(negatedTypesControlFlowNarrowing.ts, 5, 50)) +>cb : Symbol(cb, Decl(negatedTypesControlFlowNarrowing.ts, 6, 44)) + +const item = {}; +>item : Symbol(item, Decl(negatedTypesControlFlowNarrowing.ts, 8, 5)) + +if (typeof item === "string") { +>item : Symbol(item, Decl(negatedTypesControlFlowNarrowing.ts, 8, 5)) + + wantsStr(item); // item: string +>wantsStr : Symbol(wantsStr, Decl(negatedTypesControlFlowNarrowing.ts, 0, 0)) +>item : Symbol(item, Decl(negatedTypesControlFlowNarrowing.ts, 8, 5)) + +} else { + wantsNotStr(item); // item: {} & not string +>wantsNotStr : Symbol(wantsNotStr, Decl(negatedTypesControlFlowNarrowing.ts, 4, 43)) +>item : Symbol(item, Decl(negatedTypesControlFlowNarrowing.ts, 8, 5)) + + // The negation also flows through an arrow function body (a position a syntactic check misses). + wantsNegatedCallbackResult(() => item); // item: {} & not string +>wantsNegatedCallbackResult : Symbol(wantsNegatedCallbackResult, Decl(negatedTypesControlFlowNarrowing.ts, 5, 50)) +>item : Symbol(item, Decl(negatedTypesControlFlowNarrowing.ts, 8, 5)) +} + +// No negation is introduced against a disjoint union: 'not number' reduces away. +declare const value: string | number; +>value : Symbol(value, Decl(negatedTypesControlFlowNarrowing.ts, 19, 13)) + +if (typeof value === "string") { +>value : Symbol(value, Decl(negatedTypesControlFlowNarrowing.ts, 19, 13)) + + value; // string +>value : Symbol(value, Decl(negatedTypesControlFlowNarrowing.ts, 19, 13)) + +} else { + value; // number +>value : Symbol(value, Decl(negatedTypesControlFlowNarrowing.ts, 19, 13)) +} + +// Union base where the negation is redundant against every constituent. +declare function wantsNotNum(x: not number): void; +>wantsNotNum : Symbol(wantsNotNum, Decl(negatedTypesControlFlowNarrowing.ts, 24, 1)) +>x : Symbol(x, Decl(negatedTypesControlFlowNarrowing.ts, 27, 29)) + +declare const u: string | number | boolean; +>u : Symbol(u, Decl(negatedTypesControlFlowNarrowing.ts, 28, 13)) + +if (typeof u === "number") { +>u : Symbol(u, Decl(negatedTypesControlFlowNarrowing.ts, 28, 13)) + + u; // number +>u : Symbol(u, Decl(negatedTypesControlFlowNarrowing.ts, 28, 13)) + +} else { + wantsNotNum(u); // string | boolean +>wantsNotNum : Symbol(wantsNotNum, Decl(negatedTypesControlFlowNarrowing.ts, 24, 1)) +>u : Symbol(u, Decl(negatedTypesControlFlowNarrowing.ts, 28, 13)) +} + +// The value flows into a negated position nested inside an object literal argument. +declare function wantsNestedNegated(x: { member: not string }): void; +>wantsNestedNegated : Symbol(wantsNestedNegated, Decl(negatedTypesControlFlowNarrowing.ts, 33, 1)) +>x : Symbol(x, Decl(negatedTypesControlFlowNarrowing.ts, 36, 36)) +>member : Symbol(member, Decl(negatedTypesControlFlowNarrowing.ts, 36, 40)) + +declare const nested: {}; +>nested : Symbol(nested, Decl(negatedTypesControlFlowNarrowing.ts, 37, 13)) + +if (typeof nested === "string") { +>nested : Symbol(nested, Decl(negatedTypesControlFlowNarrowing.ts, 37, 13)) + + nested; // string +>nested : Symbol(nested, Decl(negatedTypesControlFlowNarrowing.ts, 37, 13)) + +} else { + wantsNestedNegated({ member: nested }); // nested: {} & not string +>wantsNestedNegated : Symbol(wantsNestedNegated, Decl(negatedTypesControlFlowNarrowing.ts, 33, 1)) +>member : Symbol(member, Decl(negatedTypesControlFlowNarrowing.ts, 41, 24)) +>nested : Symbol(nested, Decl(negatedTypesControlFlowNarrowing.ts, 37, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlowNarrowing.types b/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlowNarrowing.types new file mode 100644 index 0000000000000..0ed0baf2eb20f --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesControlFlowNarrowing.types @@ -0,0 +1,117 @@ +//// [tests/cases/conformance/types/negated/negatedTypesControlFlowNarrowing.ts] //// + +=== negatedTypesControlFlowNarrowing.ts === +// Control flow narrowing introduces negated types in the false branch of a narrowing check. +// The negation is only retained where it is non-redundant (i.e. the narrowed base type overlaps +// the removed candidate, such as `{}` / `unknown`); for ordinary disjoint unions it reduces away. + +declare function wantsStr(x: string): void; +>wantsStr : (x: string) => void +>x : string + +declare function wantsNotStr(x: not string): void; +>wantsNotStr : (x: not string) => void +>x : not string + +declare function wantsNegatedCallbackResult(cb: () => not string): void; +>wantsNegatedCallbackResult : (cb: () => not string) => void +>cb : () => not string + +const item = {}; +>item : {} +>{} : {} + +if (typeof item === "string") { +>typeof item === "string" : boolean +>typeof item : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>item : {} +>"string" : "string" + + wantsStr(item); // item: string +>wantsStr(item) : void +>wantsStr : (x: string) => void +>item : string + +} else { + wantsNotStr(item); // item: {} & not string +>wantsNotStr(item) : void +>wantsNotStr : (x: not string) => void +>item : {} & not string + + // The negation also flows through an arrow function body (a position a syntactic check misses). + wantsNegatedCallbackResult(() => item); // item: {} & not string +>wantsNegatedCallbackResult(() => item) : void +>wantsNegatedCallbackResult : (cb: () => not string) => void +>() => item : () => {} & not string +>item : {} & not string +} + +// No negation is introduced against a disjoint union: 'not number' reduces away. +declare const value: string | number; +>value : string | number + +if (typeof value === "string") { +>typeof value === "string" : boolean +>typeof value : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>value : string | number +>"string" : "string" + + value; // string +>value : string + +} else { + value; // number +>value : number +} + +// Union base where the negation is redundant against every constituent. +declare function wantsNotNum(x: not number): void; +>wantsNotNum : (x: not number) => void +>x : not number + +declare const u: string | number | boolean; +>u : string | number | boolean + +if (typeof u === "number") { +>typeof u === "number" : boolean +>typeof u : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>u : string | number | boolean +>"number" : "number" + + u; // number +>u : number + +} else { + wantsNotNum(u); // string | boolean +>wantsNotNum(u) : void +>wantsNotNum : (x: not number) => void +>u : string | boolean +} + +// The value flows into a negated position nested inside an object literal argument. +declare function wantsNestedNegated(x: { member: not string }): void; +>wantsNestedNegated : (x: { member: not string; }) => void +>x : { member: not string; } +>member : not string + +declare const nested: {}; +>nested : {} + +if (typeof nested === "string") { +>typeof nested === "string" : boolean +>typeof nested : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" +>nested : {} +>"string" : "string" + + nested; // string +>nested : string + +} else { + wantsNestedNegated({ member: nested }); // nested: {} & not string +>wantsNestedNegated({ member: nested }) : void +>wantsNestedNegated : (x: { member: not string; }) => void +>{ member: nested } : { member: {} & not string; } +>member : {} & not string +>nested : {} & not string +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesDeMorgan.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesDeMorgan.errors.txt new file mode 100644 index 0000000000000..68fff19934f47 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesDeMorgan.errors.txt @@ -0,0 +1,65 @@ +negatedTypesDeMorgan.ts(30,1): error TS2322: Type 'NotAorNotB' is not assignable to type 'not A & not B'. + Type 'not A' is not assignable to type 'not A & not B'. + Type 'unknown' is not assignable to type 'not A & not B'. + Type 'unknown' is not assignable to type 'not A'. + Type 'not A' is not assignable to type 'not B'. + Property 'a' is missing in type 'B' but required in type 'A'. +negatedTypesDeMorgan.ts(36,1): error TS2322: Type 'A & B' is not assignable to type 'not A & not B'. + Type 'A & B' is not assignable to type 'not A'. +negatedTypesDeMorgan.ts(37,1): error TS2322: Type 'A' is not assignable to type 'not A & not B'. + Type 'A' is not assignable to type 'not A'. + + +==== negatedTypesDeMorgan.ts (3 errors) ==== + // De Morgan behavior and union/intersection interaction for negated types. + + type A = { a: number }; + type B = { b: number }; + + // not (A | B) is distributed to not A & not B. + type NotAorB = not (A | B); + + // not (A & B) stays as a single negation of the intersection. + type NotAandB = not (A & B); + + // A union of negations (not simplified by De Morgan in this direction). + type NotAorNotB = not A | not B; + + // An intersection of negations equals the negation of the union. + type NotAandNotB = not A & not B; + + // Primitive forms. + type NotStringOrNumber = not (string | number); // not string & not number + type NotStringAndNever = not string | not never; // not never => unknown, so union widens + + // Assignability relationships between the forms. + declare let notAorB: NotAorB; // not A & not B + declare let notAandNotB: NotAandNotB; // not A & not B + + notAorB = notAandNotB; // should be ok (same type) + notAandNotB = notAorB; // should be ok (same type) + + declare let notAorNotB: NotAorNotB; // not A | not B + notAorB = notAorNotB; // relationship probe + ~~~~~~~ +!!! error TS2322: Type 'NotAorNotB' is not assignable to type 'not A & not B'. +!!! error TS2322: Type 'not A' is not assignable to type 'not A & not B'. +!!! error TS2322: Type 'unknown' is not assignable to type 'not A & not B'. +!!! error TS2322: Type 'unknown' is not assignable to type 'not A'. +!!! error TS2322: Type 'not A' is not assignable to type 'not B'. +!!! error TS2322: Property 'a' is missing in type 'B' but required in type 'A'. +!!! related TS2728 negatedTypesDeMorgan.ts:3:12: 'a' is declared here. + notAorNotB = notAorB; // relationship probe + + // Concrete values against the distributed intersection. + declare let ab: A & B; + declare let aOnly: A; + notAorB = ab; // probe: A & B excluded by both negations? + ~~~~~~~ +!!! error TS2322: Type 'A & B' is not assignable to type 'not A & not B'. +!!! error TS2322: Type 'A & B' is not assignable to type 'not A'. + notAorB = aOnly; // probe: A excluded by not A + ~~~~~~~ +!!! error TS2322: Type 'A' is not assignable to type 'not A & not B'. +!!! error TS2322: Type 'A' is not assignable to type 'not A'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesDeMorgan.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesDeMorgan.symbols new file mode 100644 index 0000000000000..158845d4e3b05 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesDeMorgan.symbols @@ -0,0 +1,91 @@ +//// [tests/cases/conformance/types/negated/negatedTypesDeMorgan.ts] //// + +=== negatedTypesDeMorgan.ts === +// De Morgan behavior and union/intersection interaction for negated types. + +type A = { a: number }; +>A : Symbol(A, Decl(negatedTypesDeMorgan.ts, 0, 0)) +>a : Symbol(a, Decl(negatedTypesDeMorgan.ts, 2, 10)) + +type B = { b: number }; +>B : Symbol(B, Decl(negatedTypesDeMorgan.ts, 2, 23)) +>b : Symbol(b, Decl(negatedTypesDeMorgan.ts, 3, 10)) + +// not (A | B) is distributed to not A & not B. +type NotAorB = not (A | B); +>NotAorB : Symbol(NotAorB, Decl(negatedTypesDeMorgan.ts, 3, 23)) +>A : Symbol(A, Decl(negatedTypesDeMorgan.ts, 0, 0)) +>B : Symbol(B, Decl(negatedTypesDeMorgan.ts, 2, 23)) + +// not (A & B) stays as a single negation of the intersection. +type NotAandB = not (A & B); +>NotAandB : Symbol(NotAandB, Decl(negatedTypesDeMorgan.ts, 6, 27)) +>A : Symbol(A, Decl(negatedTypesDeMorgan.ts, 0, 0)) +>B : Symbol(B, Decl(negatedTypesDeMorgan.ts, 2, 23)) + +// A union of negations (not simplified by De Morgan in this direction). +type NotAorNotB = not A | not B; +>NotAorNotB : Symbol(NotAorNotB, Decl(negatedTypesDeMorgan.ts, 9, 28)) +>A : Symbol(A, Decl(negatedTypesDeMorgan.ts, 0, 0)) +>B : Symbol(B, Decl(negatedTypesDeMorgan.ts, 2, 23)) + +// An intersection of negations equals the negation of the union. +type NotAandNotB = not A & not B; +>NotAandNotB : Symbol(NotAandNotB, Decl(negatedTypesDeMorgan.ts, 12, 32)) +>A : Symbol(A, Decl(negatedTypesDeMorgan.ts, 0, 0)) +>B : Symbol(B, Decl(negatedTypesDeMorgan.ts, 2, 23)) + +// Primitive forms. +type NotStringOrNumber = not (string | number); // not string & not number +>NotStringOrNumber : Symbol(NotStringOrNumber, Decl(negatedTypesDeMorgan.ts, 15, 33)) + +type NotStringAndNever = not string | not never; // not never => unknown, so union widens +>NotStringAndNever : Symbol(NotStringAndNever, Decl(negatedTypesDeMorgan.ts, 18, 47)) + +// Assignability relationships between the forms. +declare let notAorB: NotAorB; // not A & not B +>notAorB : Symbol(notAorB, Decl(negatedTypesDeMorgan.ts, 22, 11)) +>NotAorB : Symbol(NotAorB, Decl(negatedTypesDeMorgan.ts, 3, 23)) + +declare let notAandNotB: NotAandNotB; // not A & not B +>notAandNotB : Symbol(notAandNotB, Decl(negatedTypesDeMorgan.ts, 23, 11)) +>NotAandNotB : Symbol(NotAandNotB, Decl(negatedTypesDeMorgan.ts, 12, 32)) + +notAorB = notAandNotB; // should be ok (same type) +>notAorB : Symbol(notAorB, Decl(negatedTypesDeMorgan.ts, 22, 11)) +>notAandNotB : Symbol(notAandNotB, Decl(negatedTypesDeMorgan.ts, 23, 11)) + +notAandNotB = notAorB; // should be ok (same type) +>notAandNotB : Symbol(notAandNotB, Decl(negatedTypesDeMorgan.ts, 23, 11)) +>notAorB : Symbol(notAorB, Decl(negatedTypesDeMorgan.ts, 22, 11)) + +declare let notAorNotB: NotAorNotB; // not A | not B +>notAorNotB : Symbol(notAorNotB, Decl(negatedTypesDeMorgan.ts, 28, 11)) +>NotAorNotB : Symbol(NotAorNotB, Decl(negatedTypesDeMorgan.ts, 9, 28)) + +notAorB = notAorNotB; // relationship probe +>notAorB : Symbol(notAorB, Decl(negatedTypesDeMorgan.ts, 22, 11)) +>notAorNotB : Symbol(notAorNotB, Decl(negatedTypesDeMorgan.ts, 28, 11)) + +notAorNotB = notAorB; // relationship probe +>notAorNotB : Symbol(notAorNotB, Decl(negatedTypesDeMorgan.ts, 28, 11)) +>notAorB : Symbol(notAorB, Decl(negatedTypesDeMorgan.ts, 22, 11)) + +// Concrete values against the distributed intersection. +declare let ab: A & B; +>ab : Symbol(ab, Decl(negatedTypesDeMorgan.ts, 33, 11)) +>A : Symbol(A, Decl(negatedTypesDeMorgan.ts, 0, 0)) +>B : Symbol(B, Decl(negatedTypesDeMorgan.ts, 2, 23)) + +declare let aOnly: A; +>aOnly : Symbol(aOnly, Decl(negatedTypesDeMorgan.ts, 34, 11)) +>A : Symbol(A, Decl(negatedTypesDeMorgan.ts, 0, 0)) + +notAorB = ab; // probe: A & B excluded by both negations? +>notAorB : Symbol(notAorB, Decl(negatedTypesDeMorgan.ts, 22, 11)) +>ab : Symbol(ab, Decl(negatedTypesDeMorgan.ts, 33, 11)) + +notAorB = aOnly; // probe: A excluded by not A +>notAorB : Symbol(notAorB, Decl(negatedTypesDeMorgan.ts, 22, 11)) +>aOnly : Symbol(aOnly, Decl(negatedTypesDeMorgan.ts, 34, 11)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesDeMorgan.types b/tsc/testdata/baselines/reference/conformance/negatedTypesDeMorgan.types new file mode 100644 index 0000000000000..b93e754777fd2 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesDeMorgan.types @@ -0,0 +1,83 @@ +//// [tests/cases/conformance/types/negated/negatedTypesDeMorgan.ts] //// + +=== negatedTypesDeMorgan.ts === +// De Morgan behavior and union/intersection interaction for negated types. + +type A = { a: number }; +>A : A +>a : number + +type B = { b: number }; +>B : B +>b : number + +// not (A | B) is distributed to not A & not B. +type NotAorB = not (A | B); +>NotAorB : not A & not B + +// not (A & B) stays as a single negation of the intersection. +type NotAandB = not (A & B); +>NotAandB : not (A & B) + +// A union of negations (not simplified by De Morgan in this direction). +type NotAorNotB = not A | not B; +>NotAorNotB : NotAorNotB + +// An intersection of negations equals the negation of the union. +type NotAandNotB = not A & not B; +>NotAandNotB : NotAandNotB + +// Primitive forms. +type NotStringOrNumber = not (string | number); // not string & not number +>NotStringOrNumber : not string & not number + +type NotStringAndNever = not string | not never; // not never => unknown, so union widens +>NotStringAndNever : unknown + +// Assignability relationships between the forms. +declare let notAorB: NotAorB; // not A & not B +>notAorB : not A & not B + +declare let notAandNotB: NotAandNotB; // not A & not B +>notAandNotB : NotAandNotB + +notAorB = notAandNotB; // should be ok (same type) +>notAorB = notAandNotB : NotAandNotB +>notAorB : not A & not B +>notAandNotB : NotAandNotB + +notAandNotB = notAorB; // should be ok (same type) +>notAandNotB = notAorB : not A & not B +>notAandNotB : NotAandNotB +>notAorB : not A & not B + +declare let notAorNotB: NotAorNotB; // not A | not B +>notAorNotB : NotAorNotB + +notAorB = notAorNotB; // relationship probe +>notAorB = notAorNotB : NotAorNotB +>notAorB : not A & not B +>notAorNotB : NotAorNotB + +notAorNotB = notAorB; // relationship probe +>notAorNotB = notAorB : not A & not B +>notAorNotB : NotAorNotB +>notAorB : not A & not B + +// Concrete values against the distributed intersection. +declare let ab: A & B; +>ab : A & B + +declare let aOnly: A; +>aOnly : A + +notAorB = ab; // probe: A & B excluded by both negations? +>notAorB = ab : A & B +>notAorB : not A & not B +>ab : A & B + +notAorB = aOnly; // probe: A excluded by not A +>notAorB = aOnly : A +>notAorB : not A & not B +>aOnly : A + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesDeclarationEmit.js b/tsc/testdata/baselines/reference/conformance/negatedTypesDeclarationEmit.js new file mode 100644 index 0000000000000..334143fa512ff --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesDeclarationEmit.js @@ -0,0 +1,55 @@ +//// [tests/cases/conformance/types/negated/negatedTypesDeclarationEmit.ts] //// + +//// [negatedTypesDeclarationEmit.ts] +// Declaration emit round-trip for negated types. +// Each exported declaration should print its `not` type faithfully in the .d.ts. + +export type NotString = not string; + +export type NotUnionOfLiterals = not ("a" | "b" | "c"); + +export type NotObject = not { x: number }; + +export declare let notNumber: not number; + +export declare function accept(x: not null): void; + +export declare function make(value: T): T; + +export interface Holder { + value: not boolean; + readonly tag: string & not "reserved"; +} + +export type IndexNoMethod = { + [idx: string & not "method"]: number; +}; + +export declare const nested: not (string | { y: not number }); + + +//// [negatedTypesDeclarationEmit.js] +// Declaration emit round-trip for negated types. +// Each exported declaration should print its `not` type faithfully in the .d.ts. +export {}; + + +//// [negatedTypesDeclarationEmit.d.ts] +export type NotString = not string; +export type NotUnionOfLiterals = not ("a" | "b" | "c"); +export type NotObject = not { + x: number; +}; +export declare let notNumber: not number; +export declare function accept(x: not null): void; +export declare function make(value: T): T; +export interface Holder { + value: not boolean; + readonly tag: string & not "reserved"; +} +export type IndexNoMethod = { + [idx: string & not "method"]: number; +}; +export declare const nested: not (string | { + y: not number; +}); diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesDeclarationEmit.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesDeclarationEmit.symbols new file mode 100644 index 0000000000000..337d8bb5726dc --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesDeclarationEmit.symbols @@ -0,0 +1,52 @@ +//// [tests/cases/conformance/types/negated/negatedTypesDeclarationEmit.ts] //// + +=== negatedTypesDeclarationEmit.ts === +// Declaration emit round-trip for negated types. +// Each exported declaration should print its `not` type faithfully in the .d.ts. + +export type NotString = not string; +>NotString : Symbol(NotString, Decl(negatedTypesDeclarationEmit.ts, 0, 0)) + +export type NotUnionOfLiterals = not ("a" | "b" | "c"); +>NotUnionOfLiterals : Symbol(NotUnionOfLiterals, Decl(negatedTypesDeclarationEmit.ts, 3, 35)) + +export type NotObject = not { x: number }; +>NotObject : Symbol(NotObject, Decl(negatedTypesDeclarationEmit.ts, 5, 55)) +>x : Symbol(x, Decl(negatedTypesDeclarationEmit.ts, 7, 29)) + +export declare let notNumber: not number; +>notNumber : Symbol(notNumber, Decl(negatedTypesDeclarationEmit.ts, 9, 18)) + +export declare function accept(x: not null): void; +>accept : Symbol(accept, Decl(negatedTypesDeclarationEmit.ts, 9, 41)) +>x : Symbol(x, Decl(negatedTypesDeclarationEmit.ts, 11, 31)) + +export declare function make(value: T): T; +>make : Symbol(make, Decl(negatedTypesDeclarationEmit.ts, 11, 50)) +>T : Symbol(T, Decl(negatedTypesDeclarationEmit.ts, 13, 29)) +>value : Symbol(value, Decl(negatedTypesDeclarationEmit.ts, 13, 54)) +>T : Symbol(T, Decl(negatedTypesDeclarationEmit.ts, 13, 29)) +>T : Symbol(T, Decl(negatedTypesDeclarationEmit.ts, 13, 29)) + +export interface Holder { +>Holder : Symbol(Holder, Decl(negatedTypesDeclarationEmit.ts, 13, 67)) + + value: not boolean; +>value : Symbol(Holder.value, Decl(negatedTypesDeclarationEmit.ts, 15, 25)) + + readonly tag: string & not "reserved"; +>tag : Symbol(Holder.tag, Decl(negatedTypesDeclarationEmit.ts, 16, 23)) +} + +export type IndexNoMethod = { +>IndexNoMethod : Symbol(IndexNoMethod, Decl(negatedTypesDeclarationEmit.ts, 18, 1)) + + [idx: string & not "method"]: number; +>idx : Symbol(idx, Decl(negatedTypesDeclarationEmit.ts, 21, 5)) + +}; + +export declare const nested: not (string | { y: not number }); +>nested : Symbol(nested, Decl(negatedTypesDeclarationEmit.ts, 24, 20)) +>y : Symbol(y, Decl(negatedTypesDeclarationEmit.ts, 24, 44)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesDeclarationEmit.types b/tsc/testdata/baselines/reference/conformance/negatedTypesDeclarationEmit.types new file mode 100644 index 0000000000000..8b0dded695ee8 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesDeclarationEmit.types @@ -0,0 +1,47 @@ +//// [tests/cases/conformance/types/negated/negatedTypesDeclarationEmit.ts] //// + +=== negatedTypesDeclarationEmit.ts === +// Declaration emit round-trip for negated types. +// Each exported declaration should print its `not` type faithfully in the .d.ts. + +export type NotString = not string; +>NotString : not string + +export type NotUnionOfLiterals = not ("a" | "b" | "c"); +>NotUnionOfLiterals : not "a" & not "b" & not "c" + +export type NotObject = not { x: number }; +>NotObject : not { x: number; } +>x : number + +export declare let notNumber: not number; +>notNumber : not number + +export declare function accept(x: not null): void; +>accept : (x: not null) => void +>x : not null + +export declare function make(value: T): T; +>make : (value: T) => T +>value : T + +export interface Holder { + value: not boolean; +>value : not false & not true + + readonly tag: string & not "reserved"; +>tag : string & not "reserved" +} + +export type IndexNoMethod = { +>IndexNoMethod : IndexNoMethod + + [idx: string & not "method"]: number; +>idx : string & not "method" + +}; + +export declare const nested: not (string | { y: not number }); +>nested : not string & not { y: not number; } +>y : not number + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesGenericInference.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesGenericInference.errors.txt new file mode 100644 index 0000000000000..ffd837447e3bf --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesGenericInference.errors.txt @@ -0,0 +1,39 @@ +negatedTypesGenericInference.ts(7,28): error TS2345: Argument of type 'string' is not assignable to parameter of type 'not string'. +negatedTypesGenericInference.ts(9,20): error TS2345: Argument of type 'number' is not assignable to parameter of type 'never'. + + +==== negatedTypesGenericInference.ts (2 errors) ==== + // Generic inference from `not T` positions. + + interface Box { value: T; } + + // Inferring a type argument from a bare negated parameter position. + declare function fromNot(x: not T): T; + const r1 = fromNot("literal is irrelevant here"); // explicit T = string + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'not string'. + declare const numVal: number; + const r2 = fromNot(numVal); // T can't be inferred from a bare `not T` when the argument isn't negated -> unknown -> never (error) + ~~~~~~ +!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'never'. + + // Inferring from a negated type nested inside a generic wrapper. + declare function fromBoxNot(x: Box): T; + declare const boxNotString: Box; + const r3 = fromBoxNot(boxNotString); // T is inferred as string + + // Inferring from a negated intersection. + declare function fromStringNot(x: string & not T): T; + declare const sv: string & not "bar"; + const r4 = fromStringNot(sv); // T is inferred as "bar" + + // Inference site where the same T appears both negated and positive. + declare function both(a: T, b: not T): T; + const r5 = both("hello", 123); // T = "hello" from the first arg; 123 checked against not "hello" + + // Higher-order: mapping a negated type parameter. + type Negate = not T; + declare function viaAlias(x: Negate): T; + declare const nv: not number; + const r6 = viaAlias(nv); // T is inferred as number + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesGenericInference.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesGenericInference.symbols new file mode 100644 index 0000000000000..fc599040dd996 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesGenericInference.symbols @@ -0,0 +1,101 @@ +//// [tests/cases/conformance/types/negated/negatedTypesGenericInference.ts] //// + +=== negatedTypesGenericInference.ts === +// Generic inference from `not T` positions. + +interface Box { value: T; } +>Box : Symbol(Box, Decl(negatedTypesGenericInference.ts, 0, 0)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 2, 14)) +>value : Symbol(Box.value, Decl(negatedTypesGenericInference.ts, 2, 18)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 2, 14)) + +// Inferring a type argument from a bare negated parameter position. +declare function fromNot(x: not T): T; +>fromNot : Symbol(fromNot, Decl(negatedTypesGenericInference.ts, 2, 30)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 5, 25)) +>x : Symbol(x, Decl(negatedTypesGenericInference.ts, 5, 28)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 5, 25)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 5, 25)) + +const r1 = fromNot("literal is irrelevant here"); // explicit T = string +>r1 : Symbol(r1, Decl(negatedTypesGenericInference.ts, 6, 5)) +>fromNot : Symbol(fromNot, Decl(negatedTypesGenericInference.ts, 2, 30)) + +declare const numVal: number; +>numVal : Symbol(numVal, Decl(negatedTypesGenericInference.ts, 7, 13)) + +const r2 = fromNot(numVal); // T can't be inferred from a bare `not T` when the argument isn't negated -> unknown -> never (error) +>r2 : Symbol(r2, Decl(negatedTypesGenericInference.ts, 8, 5)) +>fromNot : Symbol(fromNot, Decl(negatedTypesGenericInference.ts, 2, 30)) +>numVal : Symbol(numVal, Decl(negatedTypesGenericInference.ts, 7, 13)) + +// Inferring from a negated type nested inside a generic wrapper. +declare function fromBoxNot(x: Box): T; +>fromBoxNot : Symbol(fromBoxNot, Decl(negatedTypesGenericInference.ts, 8, 27)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 11, 28)) +>x : Symbol(x, Decl(negatedTypesGenericInference.ts, 11, 31)) +>Box : Symbol(Box, Decl(negatedTypesGenericInference.ts, 0, 0)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 11, 28)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 11, 28)) + +declare const boxNotString: Box; +>boxNotString : Symbol(boxNotString, Decl(negatedTypesGenericInference.ts, 12, 13)) +>Box : Symbol(Box, Decl(negatedTypesGenericInference.ts, 0, 0)) + +const r3 = fromBoxNot(boxNotString); // T is inferred as string +>r3 : Symbol(r3, Decl(negatedTypesGenericInference.ts, 13, 5)) +>fromBoxNot : Symbol(fromBoxNot, Decl(negatedTypesGenericInference.ts, 8, 27)) +>boxNotString : Symbol(boxNotString, Decl(negatedTypesGenericInference.ts, 12, 13)) + +// Inferring from a negated intersection. +declare function fromStringNot(x: string & not T): T; +>fromStringNot : Symbol(fromStringNot, Decl(negatedTypesGenericInference.ts, 13, 36)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 16, 31)) +>x : Symbol(x, Decl(negatedTypesGenericInference.ts, 16, 49)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 16, 31)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 16, 31)) + +declare const sv: string & not "bar"; +>sv : Symbol(sv, Decl(negatedTypesGenericInference.ts, 17, 13)) + +const r4 = fromStringNot(sv); // T is inferred as "bar" +>r4 : Symbol(r4, Decl(negatedTypesGenericInference.ts, 18, 5)) +>fromStringNot : Symbol(fromStringNot, Decl(negatedTypesGenericInference.ts, 13, 36)) +>sv : Symbol(sv, Decl(negatedTypesGenericInference.ts, 17, 13)) + +// Inference site where the same T appears both negated and positive. +declare function both(a: T, b: not T): T; +>both : Symbol(both, Decl(negatedTypesGenericInference.ts, 18, 29)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 21, 22)) +>a : Symbol(a, Decl(negatedTypesGenericInference.ts, 21, 25)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 21, 22)) +>b : Symbol(b, Decl(negatedTypesGenericInference.ts, 21, 30)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 21, 22)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 21, 22)) + +const r5 = both("hello", 123); // T = "hello" from the first arg; 123 checked against not "hello" +>r5 : Symbol(r5, Decl(negatedTypesGenericInference.ts, 22, 5)) +>both : Symbol(both, Decl(negatedTypesGenericInference.ts, 18, 29)) + +// Higher-order: mapping a negated type parameter. +type Negate = not T; +>Negate : Symbol(Negate, Decl(negatedTypesGenericInference.ts, 22, 30)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 25, 12)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 25, 12)) + +declare function viaAlias(x: Negate): T; +>viaAlias : Symbol(viaAlias, Decl(negatedTypesGenericInference.ts, 25, 23)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 26, 26)) +>x : Symbol(x, Decl(negatedTypesGenericInference.ts, 26, 29)) +>Negate : Symbol(Negate, Decl(negatedTypesGenericInference.ts, 22, 30)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 26, 26)) +>T : Symbol(T, Decl(negatedTypesGenericInference.ts, 26, 26)) + +declare const nv: not number; +>nv : Symbol(nv, Decl(negatedTypesGenericInference.ts, 27, 13)) + +const r6 = viaAlias(nv); // T is inferred as number +>r6 : Symbol(r6, Decl(negatedTypesGenericInference.ts, 28, 5)) +>viaAlias : Symbol(viaAlias, Decl(negatedTypesGenericInference.ts, 25, 23)) +>nv : Symbol(nv, Decl(negatedTypesGenericInference.ts, 27, 13)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesGenericInference.types b/tsc/testdata/baselines/reference/conformance/negatedTypesGenericInference.types new file mode 100644 index 0000000000000..1103fd8314fb6 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesGenericInference.types @@ -0,0 +1,86 @@ +//// [tests/cases/conformance/types/negated/negatedTypesGenericInference.ts] //// + +=== negatedTypesGenericInference.ts === +// Generic inference from `not T` positions. + +interface Box { value: T; } +>value : T + +// Inferring a type argument from a bare negated parameter position. +declare function fromNot(x: not T): T; +>fromNot : (x: not T) => T +>x : not T + +const r1 = fromNot("literal is irrelevant here"); // explicit T = string +>r1 : string +>fromNot("literal is irrelevant here") : string +>fromNot : (x: not T) => T +>"literal is irrelevant here" : "literal is irrelevant here" + +declare const numVal: number; +>numVal : number + +const r2 = fromNot(numVal); // T can't be inferred from a bare `not T` when the argument isn't negated -> unknown -> never (error) +>r2 : unknown +>fromNot(numVal) : unknown +>fromNot : (x: not T) => T +>numVal : number + +// Inferring from a negated type nested inside a generic wrapper. +declare function fromBoxNot(x: Box): T; +>fromBoxNot : (x: Box) => T +>x : Box + +declare const boxNotString: Box; +>boxNotString : Box + +const r3 = fromBoxNot(boxNotString); // T is inferred as string +>r3 : string +>fromBoxNot(boxNotString) : string +>fromBoxNot : (x: Box) => T +>boxNotString : Box + +// Inferring from a negated intersection. +declare function fromStringNot(x: string & not T): T; +>fromStringNot : (x: string & not T) => T +>x : string & not T + +declare const sv: string & not "bar"; +>sv : string & not "bar" + +const r4 = fromStringNot(sv); // T is inferred as "bar" +>r4 : "bar" +>fromStringNot(sv) : "bar" +>fromStringNot : (x: string & not T) => T +>sv : string & not "bar" + +// Inference site where the same T appears both negated and positive. +declare function both(a: T, b: not T): T; +>both : (a: T, b: not T) => T +>a : T +>b : not T + +const r5 = both("hello", 123); // T = "hello" from the first arg; 123 checked against not "hello" +>r5 : "hello" +>both("hello", 123) : "hello" +>both : (a: T, b: not T) => T +>"hello" : "hello" +>123 : 123 + +// Higher-order: mapping a negated type parameter. +type Negate = not T; +>Negate : not T + +declare function viaAlias(x: Negate): T; +>viaAlias : (x: Negate) => T +>x : not T + +declare const nv: not number; +>nv : not number + +const r6 = viaAlias(nv); // T is inferred as number +>r6 : number +>viaAlias(nv) : number +>viaAlias : (x: Negate) => T +>nv : not number + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInConditionalTypesAndInfer.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesInConditionalTypesAndInfer.symbols new file mode 100644 index 0000000000000..1915765e63ea0 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInConditionalTypesAndInfer.symbols @@ -0,0 +1,94 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInConditionalTypesAndInfer.ts] //// + +=== negatedTypesInConditionalTypesAndInfer.ts === +// Negated types combined with conditional types and `infer`. + +// A conditional that tests assignability to a negated type. +type IsNotString = T extends not string ? true : false; +>IsNotString : Symbol(IsNotString, Decl(negatedTypesInConditionalTypesAndInfer.ts, 0, 0)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 3, 17)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 3, 17)) + +type A1 = IsNotString; // number is not a string -> true +>A1 : Symbol(A1, Decl(negatedTypesInConditionalTypesAndInfer.ts, 3, 58)) +>IsNotString : Symbol(IsNotString, Decl(negatedTypesInConditionalTypesAndInfer.ts, 0, 0)) + +type A2 = IsNotString<"hello">; // a string literal -> false +>A2 : Symbol(A2, Decl(negatedTypesInConditionalTypesAndInfer.ts, 4, 30)) +>IsNotString : Symbol(IsNotString, Decl(negatedTypesInConditionalTypesAndInfer.ts, 0, 0)) + +type A3 = IsNotString; // an object -> true +>A3 : Symbol(A3, Decl(negatedTypesInConditionalTypesAndInfer.ts, 5, 31)) +>IsNotString : Symbol(IsNotString, Decl(negatedTypesInConditionalTypesAndInfer.ts, 0, 0)) + +// Distributive conditional producing negated types in a branch. +type Branch = T extends string ? T : not T; +>Branch : Symbol(Branch, Decl(negatedTypesInConditionalTypesAndInfer.ts, 6, 30)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 9, 12)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 9, 12)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 9, 12)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 9, 12)) + +type B1 = Branch; // string +>B1 : Symbol(B1, Decl(negatedTypesInConditionalTypesAndInfer.ts, 9, 46)) +>Branch : Symbol(Branch, Decl(negatedTypesInConditionalTypesAndInfer.ts, 6, 30)) + +type B2 = Branch; // not number +>B2 : Symbol(B2, Decl(negatedTypesInConditionalTypesAndInfer.ts, 10, 25)) +>Branch : Symbol(Branch, Decl(negatedTypesInConditionalTypesAndInfer.ts, 6, 30)) + +type B3 = Branch; // distributes: string | not number +>B3 : Symbol(B3, Decl(negatedTypesInConditionalTypesAndInfer.ts, 11, 25)) +>Branch : Symbol(Branch, Decl(negatedTypesInConditionalTypesAndInfer.ts, 6, 30)) + +// `infer` underneath the `not` operator. +type InferUnderNot = T extends not (infer U) ? U : never; +>InferUnderNot : Symbol(InferUnderNot, Decl(negatedTypesInConditionalTypesAndInfer.ts, 12, 34)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 15, 19)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 15, 19)) +>U : Symbol(U, Decl(negatedTypesInConditionalTypesAndInfer.ts, 15, 44)) +>U : Symbol(U, Decl(negatedTypesInConditionalTypesAndInfer.ts, 15, 44)) + +type C1 = InferUnderNot; // infer binds U = string +>C1 : Symbol(C1, Decl(negatedTypesInConditionalTypesAndInfer.ts, 15, 60)) +>InferUnderNot : Symbol(InferUnderNot, Decl(negatedTypesInConditionalTypesAndInfer.ts, 12, 34)) + +type C2 = InferUnderNot; // number is not a negated type -> false branch -> never +>C2 : Symbol(C2, Decl(negatedTypesInConditionalTypesAndInfer.ts, 16, 36)) +>InferUnderNot : Symbol(InferUnderNot, Decl(negatedTypesInConditionalTypesAndInfer.ts, 12, 34)) + +// `infer` capturing a negated type. +type InferNegated = T extends Box ? U : never; +>InferNegated : Symbol(InferNegated, Decl(negatedTypesInConditionalTypesAndInfer.ts, 17, 32)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 20, 18)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 20, 18)) +>Box : Symbol(Box, Decl(negatedTypesInConditionalTypesAndInfer.ts, 20, 58)) +>U : Symbol(U, Decl(negatedTypesInConditionalTypesAndInfer.ts, 20, 42)) +>U : Symbol(U, Decl(negatedTypesInConditionalTypesAndInfer.ts, 20, 42)) + +interface Box { value: T; } +>Box : Symbol(Box, Decl(negatedTypesInConditionalTypesAndInfer.ts, 20, 58)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 21, 14)) +>value : Symbol(Box.value, Decl(negatedTypesInConditionalTypesAndInfer.ts, 21, 18)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 21, 14)) + +type D1 = InferNegated>; // U should be not string +>D1 : Symbol(D1, Decl(negatedTypesInConditionalTypesAndInfer.ts, 21, 30)) +>InferNegated : Symbol(InferNegated, Decl(negatedTypesInConditionalTypesAndInfer.ts, 17, 32)) +>Box : Symbol(Box, Decl(negatedTypesInConditionalTypesAndInfer.ts, 20, 58)) + +// Conditional constraint using not. +type NonNullish = T extends not (null | undefined) ? T : never; +>NonNullish : Symbol(NonNullish, Decl(negatedTypesInConditionalTypesAndInfer.ts, 22, 40)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 25, 16)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 25, 16)) +>T : Symbol(T, Decl(negatedTypesInConditionalTypesAndInfer.ts, 25, 16)) + +type E1 = NonNullish; // distributes to string +>E1 : Symbol(E1, Decl(negatedTypesInConditionalTypesAndInfer.ts, 25, 66)) +>NonNullish : Symbol(NonNullish, Decl(negatedTypesInConditionalTypesAndInfer.ts, 22, 40)) + +type E2 = NonNullish; // never +>E2 : Symbol(E2, Decl(negatedTypesInConditionalTypesAndInfer.ts, 26, 36)) +>NonNullish : Symbol(NonNullish, Decl(negatedTypesInConditionalTypesAndInfer.ts, 22, 40)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInConditionalTypesAndInfer.types b/tsc/testdata/baselines/reference/conformance/negatedTypesInConditionalTypesAndInfer.types new file mode 100644 index 0000000000000..e9dfd0881451e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInConditionalTypesAndInfer.types @@ -0,0 +1,63 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInConditionalTypesAndInfer.ts] //// + +=== negatedTypesInConditionalTypesAndInfer.ts === +// Negated types combined with conditional types and `infer`. + +// A conditional that tests assignability to a negated type. +type IsNotString = T extends not string ? true : false; +>IsNotString : IsNotString +>true : true +>false : false + +type A1 = IsNotString; // number is not a string -> true +>A1 : true + +type A2 = IsNotString<"hello">; // a string literal -> false +>A2 : false + +type A3 = IsNotString; // an object -> true +>A3 : true + +// Distributive conditional producing negated types in a branch. +type Branch = T extends string ? T : not T; +>Branch : Branch + +type B1 = Branch; // string +>B1 : string + +type B2 = Branch; // not number +>B2 : not number + +type B3 = Branch; // distributes: string | not number +>B3 : B3 + +// `infer` underneath the `not` operator. +type InferUnderNot = T extends not (infer U) ? U : never; +>InferUnderNot : InferUnderNot + +type C1 = InferUnderNot; // infer binds U = string +>C1 : string + +type C2 = InferUnderNot; // number is not a negated type -> false branch -> never +>C2 : never + +// `infer` capturing a negated type. +type InferNegated = T extends Box ? U : never; +>InferNegated : InferNegated + +interface Box { value: T; } +>value : T + +type D1 = InferNegated>; // U should be not string +>D1 : not string + +// Conditional constraint using not. +type NonNullish = T extends not (null | undefined) ? T : never; +>NonNullish : NonNullish + +type E1 = NonNullish; // distributes to string +>E1 : string + +type E2 = NonNullish; // never +>E2 : never + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInIndexSignatures.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesInIndexSignatures.errors.txt new file mode 100644 index 0000000000000..e3d70e2ee9b70 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInIndexSignatures.errors.txt @@ -0,0 +1,65 @@ +negatedTypesInIndexSignatures.ts(10,10): error TS2339: Property 'method' does not exist on type 'NoMethod'. +negatedTypesInIndexSignatures.ts(20,6): error TS2339: Property 'a' does not exist on type 'NoAB'. +negatedTypesInIndexSignatures.ts(21,6): error TS2339: Property 'b' does not exist on type 'NoAB'. +negatedTypesInIndexSignatures.ts(40,5): error TS2322: Type 'number' is not assignable to type 'string'. +negatedTypesInIndexSignatures.ts(45,6): error TS1268: An index signature parameter type must be 'string', 'number', 'symbol', or a template literal type. + + +==== negatedTypesInIndexSignatures.ts (5 errors) ==== + // Negated types used to build index signature key types. + + // The canonical example: a string index that excludes a specific key. + type NoMethod = { + [idx: string & not "method"]: number; + }; + + declare let noMethod: NoMethod; + noMethod.foo = 1; // ok + noMethod.method = 1; // excluded key + ~~~~~~ +!!! error TS2339: Property 'method' does not exist on type 'NoMethod'. + noMethod["bar"] = 2; // ok + + // Excluding a union of keys. + type NoAB = { + [idx: string & not ("a" | "b")]: number; + }; + + declare let noAB: NoAB; + noAB.c = 1; // ok + noAB.a = 1; // excluded key + ~ +!!! error TS2339: Property 'a' does not exist on type 'NoAB'. + noAB.b = 1; // excluded key + ~ +!!! error TS2339: Property 'b' does not exist on type 'NoAB'. + + // Mapped-type form that produces the same key type. + type Config = { + foo: number; + bar: number; + } & { + [k in (string & not ("foo" | "bar"))]: string; + }; + + const conf: Config = { + foo: 12, + bar: 12, + other: "string", + }; // ok + + const conf2: Config = { + foo: 12, + bar: 12, + other: 0, + ~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }; // other should be a string + + // A bare negated type as an index key (not intersected with string). + type BareNegated = { + [idx: not "method"]: number; + ~~~ +!!! error TS1268: An index signature parameter type must be 'string', 'number', 'symbol', or a template literal type. + }; + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInIndexSignatures.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesInIndexSignatures.symbols new file mode 100644 index 0000000000000..4d25d14704ce0 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInIndexSignatures.symbols @@ -0,0 +1,108 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInIndexSignatures.ts] //// + +=== negatedTypesInIndexSignatures.ts === +// Negated types used to build index signature key types. + +// The canonical example: a string index that excludes a specific key. +type NoMethod = { +>NoMethod : Symbol(NoMethod, Decl(negatedTypesInIndexSignatures.ts, 0, 0)) + + [idx: string & not "method"]: number; +>idx : Symbol(idx, Decl(negatedTypesInIndexSignatures.ts, 4, 5)) + +}; + +declare let noMethod: NoMethod; +>noMethod : Symbol(noMethod, Decl(negatedTypesInIndexSignatures.ts, 7, 11)) +>NoMethod : Symbol(NoMethod, Decl(negatedTypesInIndexSignatures.ts, 0, 0)) + +noMethod.foo = 1; // ok +>noMethod.foo : Symbol(__index, Decl(negatedTypesInIndexSignatures.ts, 3, 17)) +>noMethod : Symbol(noMethod, Decl(negatedTypesInIndexSignatures.ts, 7, 11)) +>foo : Symbol(__index, Decl(negatedTypesInIndexSignatures.ts, 3, 17)) + +noMethod.method = 1; // excluded key +>noMethod : Symbol(noMethod, Decl(negatedTypesInIndexSignatures.ts, 7, 11)) + +noMethod["bar"] = 2; // ok +>noMethod : Symbol(noMethod, Decl(negatedTypesInIndexSignatures.ts, 7, 11)) + +// Excluding a union of keys. +type NoAB = { +>NoAB : Symbol(NoAB, Decl(negatedTypesInIndexSignatures.ts, 10, 20)) + + [idx: string & not ("a" | "b")]: number; +>idx : Symbol(idx, Decl(negatedTypesInIndexSignatures.ts, 14, 5)) + +}; + +declare let noAB: NoAB; +>noAB : Symbol(noAB, Decl(negatedTypesInIndexSignatures.ts, 17, 11)) +>NoAB : Symbol(NoAB, Decl(negatedTypesInIndexSignatures.ts, 10, 20)) + +noAB.c = 1; // ok +>noAB.c : Symbol(__index, Decl(negatedTypesInIndexSignatures.ts, 13, 13)) +>noAB : Symbol(noAB, Decl(negatedTypesInIndexSignatures.ts, 17, 11)) +>c : Symbol(__index, Decl(negatedTypesInIndexSignatures.ts, 13, 13)) + +noAB.a = 1; // excluded key +>noAB : Symbol(noAB, Decl(negatedTypesInIndexSignatures.ts, 17, 11)) + +noAB.b = 1; // excluded key +>noAB : Symbol(noAB, Decl(negatedTypesInIndexSignatures.ts, 17, 11)) + +// Mapped-type form that produces the same key type. +type Config = { +>Config : Symbol(Config, Decl(negatedTypesInIndexSignatures.ts, 20, 11)) + + foo: number; +>foo : Symbol(foo, Decl(negatedTypesInIndexSignatures.ts, 23, 15)) + + bar: number; +>bar : Symbol(bar, Decl(negatedTypesInIndexSignatures.ts, 24, 16)) + +} & { + [k in (string & not ("foo" | "bar"))]: string; +>k : Symbol(k, Decl(negatedTypesInIndexSignatures.ts, 27, 5)) + +}; + +const conf: Config = { +>conf : Symbol(conf, Decl(negatedTypesInIndexSignatures.ts, 30, 5)) +>Config : Symbol(Config, Decl(negatedTypesInIndexSignatures.ts, 20, 11)) + + foo: 12, +>foo : Symbol(foo, Decl(negatedTypesInIndexSignatures.ts, 30, 22)) + + bar: 12, +>bar : Symbol(bar, Decl(negatedTypesInIndexSignatures.ts, 31, 12)) + + other: "string", +>other : Symbol(other, Decl(negatedTypesInIndexSignatures.ts, 32, 12)) + +}; // ok + +const conf2: Config = { +>conf2 : Symbol(conf2, Decl(negatedTypesInIndexSignatures.ts, 36, 5)) +>Config : Symbol(Config, Decl(negatedTypesInIndexSignatures.ts, 20, 11)) + + foo: 12, +>foo : Symbol(foo, Decl(negatedTypesInIndexSignatures.ts, 36, 23)) + + bar: 12, +>bar : Symbol(bar, Decl(negatedTypesInIndexSignatures.ts, 37, 12)) + + other: 0, +>other : Symbol(other, Decl(negatedTypesInIndexSignatures.ts, 38, 12)) + +}; // other should be a string + +// A bare negated type as an index key (not intersected with string). +type BareNegated = { +>BareNegated : Symbol(BareNegated, Decl(negatedTypesInIndexSignatures.ts, 40, 2)) + + [idx: not "method"]: number; +>idx : Symbol(idx, Decl(negatedTypesInIndexSignatures.ts, 44, 5)) + +}; + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInIndexSignatures.types b/tsc/testdata/baselines/reference/conformance/negatedTypesInIndexSignatures.types new file mode 100644 index 0000000000000..8e2505a0080ba --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInIndexSignatures.types @@ -0,0 +1,130 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInIndexSignatures.ts] //// + +=== negatedTypesInIndexSignatures.ts === +// Negated types used to build index signature key types. + +// The canonical example: a string index that excludes a specific key. +type NoMethod = { +>NoMethod : NoMethod + + [idx: string & not "method"]: number; +>idx : string & not "method" + +}; + +declare let noMethod: NoMethod; +>noMethod : NoMethod + +noMethod.foo = 1; // ok +>noMethod.foo = 1 : 1 +>noMethod.foo : number +>noMethod : NoMethod +>foo : number +>1 : 1 + +noMethod.method = 1; // excluded key +>noMethod.method = 1 : 1 +>noMethod.method : any +>noMethod : NoMethod +>method : any +>1 : 1 + +noMethod["bar"] = 2; // ok +>noMethod["bar"] = 2 : 2 +>noMethod["bar"] : number +>noMethod : NoMethod +>"bar" : "bar" +>2 : 2 + +// Excluding a union of keys. +type NoAB = { +>NoAB : NoAB + + [idx: string & not ("a" | "b")]: number; +>idx : string & not "a" & not "b" + +}; + +declare let noAB: NoAB; +>noAB : NoAB + +noAB.c = 1; // ok +>noAB.c = 1 : 1 +>noAB.c : number +>noAB : NoAB +>c : number +>1 : 1 + +noAB.a = 1; // excluded key +>noAB.a = 1 : 1 +>noAB.a : any +>noAB : NoAB +>a : any +>1 : 1 + +noAB.b = 1; // excluded key +>noAB.b = 1 : 1 +>noAB.b : any +>noAB : NoAB +>b : any +>1 : 1 + +// Mapped-type form that produces the same key type. +type Config = { +>Config : Config + + foo: number; +>foo : number + + bar: number; +>bar : number + +} & { + [k in (string & not ("foo" | "bar"))]: string; +}; + +const conf: Config = { +>conf : Config +>{ foo: 12, bar: 12, other: "string",} : { foo: number; bar: number; other: string; } + + foo: 12, +>foo : number +>12 : 12 + + bar: 12, +>bar : number +>12 : 12 + + other: "string", +>other : string +>"string" : "string" + +}; // ok + +const conf2: Config = { +>conf2 : Config +>{ foo: 12, bar: 12, other: 0,} : { foo: number; bar: number; other: number; } + + foo: 12, +>foo : number +>12 : 12 + + bar: 12, +>bar : number +>12 : 12 + + other: 0, +>other : number +>0 : 0 + +}; // other should be a string + +// A bare negated type as an index key (not intersected with string). +type BareNegated = { +>BareNegated : BareNegated + + [idx: not "method"]: number; +>idx : not "method" + +}; + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInKeyofAndMappedKeyRemapping.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesInKeyofAndMappedKeyRemapping.errors.txt new file mode 100644 index 0000000000000..6d34b22e8c93e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInKeyofAndMappedKeyRemapping.errors.txt @@ -0,0 +1,62 @@ +negatedTypesInKeyofAndMappedKeyRemapping.ts(32,11): error TS2339: Property 'id' does not exist on type 'WithoutId'. +negatedTypesInKeyofAndMappedKeyRemapping.ts(36,10): error TS2339: Property 'id' does not exist on type 'OnlyData'. +negatedTypesInKeyofAndMappedKeyRemapping.ts(37,10): error TS2339: Property 'method' does not exist on type 'OnlyData'. +negatedTypesInKeyofAndMappedKeyRemapping.ts(46,11): error TS2339: Property 'name' does not exist on type 'Omit2'. + + +==== negatedTypesInKeyofAndMappedKeyRemapping.ts (4 errors) ==== + // Negated types combined with keyof and mapped-type key remapping (`as`). + + interface Obj { + id: number; + name: string; + method(): void; + } + + // keyof over the object. + type K = keyof Obj; // "id" | "name" | "method" + + // Negation of a keyof union. + type NotKeyof = not keyof Obj; // not ("id" | "name" | "method") + + // keyof applied to a negated object type. + type KeyofNot = keyof (not Obj); + + // Key remapping that filters out a specific key via `as (K & not "id")`. + type WithoutId = { + [P in keyof Obj as (P & not "id")]: Obj[P]; + }; + + // Key remapping that filters out several keys. + type OnlyData = { + [P in keyof Obj as (P & not ("id" | "method"))]: Obj[P]; + }; + + // Probes against the remapped types. + declare let withoutId: WithoutId; + withoutId.name; // should exist + withoutId.method; // should exist + withoutId.id; // should be removed + ~~ +!!! error TS2339: Property 'id' does not exist on type 'WithoutId'. + + declare let onlyData: OnlyData; + onlyData.name; // should exist + onlyData.id; // should be removed + ~~ +!!! error TS2339: Property 'id' does not exist on type 'OnlyData'. + onlyData.method; // should be removed + ~~~~~~ +!!! error TS2339: Property 'method' does not exist on type 'OnlyData'. + + // Generic key filtering. + type Omit2 = { + [P in keyof T as (P & not K)]: T[P]; + }; + type ObjNoName = Omit2; + declare let objNoName: ObjNoName; + objNoName.id; // should exist + objNoName.name; // should be removed + ~~~~ +!!! error TS2339: Property 'name' does not exist on type 'Omit2'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInKeyofAndMappedKeyRemapping.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesInKeyofAndMappedKeyRemapping.symbols new file mode 100644 index 0000000000000..5ec147413f3c7 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInKeyofAndMappedKeyRemapping.symbols @@ -0,0 +1,125 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInKeyofAndMappedKeyRemapping.ts] //// + +=== negatedTypesInKeyofAndMappedKeyRemapping.ts === +// Negated types combined with keyof and mapped-type key remapping (`as`). + +interface Obj { +>Obj : Symbol(Obj, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 0, 0)) + + id: number; +>id : Symbol(Obj.id, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 2, 15)) + + name: string; +>name : Symbol(Obj.name, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 3, 15)) + + method(): void; +>method : Symbol(Obj.method, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 4, 17)) +} + +// keyof over the object. +type K = keyof Obj; // "id" | "name" | "method" +>K : Symbol(K, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 6, 1)) +>Obj : Symbol(Obj, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 0, 0)) + +// Negation of a keyof union. +type NotKeyof = not keyof Obj; // not ("id" | "name" | "method") +>NotKeyof : Symbol(NotKeyof, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 9, 19)) +>Obj : Symbol(Obj, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 0, 0)) + +// keyof applied to a negated object type. +type KeyofNot = keyof (not Obj); +>KeyofNot : Symbol(KeyofNot, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 12, 30)) +>Obj : Symbol(Obj, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 0, 0)) + +// Key remapping that filters out a specific key via `as (K & not "id")`. +type WithoutId = { +>WithoutId : Symbol(WithoutId, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 15, 32)) + + [P in keyof Obj as (P & not "id")]: Obj[P]; +>P : Symbol(P, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 19, 5)) +>Obj : Symbol(Obj, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 0, 0)) +>P : Symbol(P, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 19, 5)) +>Obj : Symbol(Obj, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 0, 0)) +>P : Symbol(P, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 19, 5)) + +}; + +// Key remapping that filters out several keys. +type OnlyData = { +>OnlyData : Symbol(OnlyData, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 20, 2)) + + [P in keyof Obj as (P & not ("id" | "method"))]: Obj[P]; +>P : Symbol(P, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 24, 5)) +>Obj : Symbol(Obj, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 0, 0)) +>P : Symbol(P, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 24, 5)) +>Obj : Symbol(Obj, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 0, 0)) +>P : Symbol(P, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 24, 5)) + +}; + +// Probes against the remapped types. +declare let withoutId: WithoutId; +>withoutId : Symbol(withoutId, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 28, 11)) +>WithoutId : Symbol(WithoutId, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 15, 32)) + +withoutId.name; // should exist +>withoutId.name : Symbol(name, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 3, 15)) +>withoutId : Symbol(withoutId, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 28, 11)) +>name : Symbol(name, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 3, 15)) + +withoutId.method; // should exist +>withoutId.method : Symbol(method, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 4, 17)) +>withoutId : Symbol(withoutId, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 28, 11)) +>method : Symbol(method, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 4, 17)) + +withoutId.id; // should be removed +>withoutId : Symbol(withoutId, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 28, 11)) + +declare let onlyData: OnlyData; +>onlyData : Symbol(onlyData, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 33, 11)) +>OnlyData : Symbol(OnlyData, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 20, 2)) + +onlyData.name; // should exist +>onlyData.name : Symbol(name, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 3, 15)) +>onlyData : Symbol(onlyData, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 33, 11)) +>name : Symbol(name, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 3, 15)) + +onlyData.id; // should be removed +>onlyData : Symbol(onlyData, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 33, 11)) + +onlyData.method; // should be removed +>onlyData : Symbol(onlyData, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 33, 11)) + +// Generic key filtering. +type Omit2 = { +>Omit2 : Symbol(Omit2, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 36, 16)) +>T : Symbol(T, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 39, 11)) +>K : Symbol(K, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 39, 13)) +>T : Symbol(T, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 39, 11)) + + [P in keyof T as (P & not K)]: T[P]; +>P : Symbol(P, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 40, 5)) +>T : Symbol(T, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 39, 11)) +>P : Symbol(P, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 40, 5)) +>K : Symbol(K, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 39, 13)) +>T : Symbol(T, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 39, 11)) +>P : Symbol(P, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 40, 5)) + +}; +type ObjNoName = Omit2; +>ObjNoName : Symbol(ObjNoName, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 41, 2)) +>Omit2 : Symbol(Omit2, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 36, 16)) +>Obj : Symbol(Obj, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 0, 0)) + +declare let objNoName: ObjNoName; +>objNoName : Symbol(objNoName, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 43, 11)) +>ObjNoName : Symbol(ObjNoName, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 41, 2)) + +objNoName.id; // should exist +>objNoName.id : Symbol(id, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 2, 15)) +>objNoName : Symbol(objNoName, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 43, 11)) +>id : Symbol(id, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 2, 15)) + +objNoName.name; // should be removed +>objNoName : Symbol(objNoName, Decl(negatedTypesInKeyofAndMappedKeyRemapping.ts, 43, 11)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInKeyofAndMappedKeyRemapping.types b/tsc/testdata/baselines/reference/conformance/negatedTypesInKeyofAndMappedKeyRemapping.types new file mode 100644 index 0000000000000..afd847f6ee18b --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInKeyofAndMappedKeyRemapping.types @@ -0,0 +1,101 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInKeyofAndMappedKeyRemapping.ts] //// + +=== negatedTypesInKeyofAndMappedKeyRemapping.ts === +// Negated types combined with keyof and mapped-type key remapping (`as`). + +interface Obj { + id: number; +>id : number + + name: string; +>name : string + + method(): void; +>method : () => void +} + +// keyof over the object. +type K = keyof Obj; // "id" | "name" | "method" +>K : keyof Obj + +// Negation of a keyof union. +type NotKeyof = not keyof Obj; // not ("id" | "name" | "method") +>NotKeyof : not "id" & not "method" & not "name" + +// keyof applied to a negated object type. +type KeyofNot = keyof (not Obj); +>KeyofNot : keyof not Obj + +// Key remapping that filters out a specific key via `as (K & not "id")`. +type WithoutId = { +>WithoutId : WithoutId + + [P in keyof Obj as (P & not "id")]: Obj[P]; +}; + +// Key remapping that filters out several keys. +type OnlyData = { +>OnlyData : OnlyData + + [P in keyof Obj as (P & not ("id" | "method"))]: Obj[P]; +}; + +// Probes against the remapped types. +declare let withoutId: WithoutId; +>withoutId : WithoutId + +withoutId.name; // should exist +>withoutId.name : string +>withoutId : WithoutId +>name : string + +withoutId.method; // should exist +>withoutId.method : () => void +>withoutId : WithoutId +>method : () => void + +withoutId.id; // should be removed +>withoutId.id : any +>withoutId : WithoutId +>id : any + +declare let onlyData: OnlyData; +>onlyData : OnlyData + +onlyData.name; // should exist +>onlyData.name : string +>onlyData : OnlyData +>name : string + +onlyData.id; // should be removed +>onlyData.id : any +>onlyData : OnlyData +>id : any + +onlyData.method; // should be removed +>onlyData.method : any +>onlyData : OnlyData +>method : any + +// Generic key filtering. +type Omit2 = { +>Omit2 : Omit2 + + [P in keyof T as (P & not K)]: T[P]; +}; +type ObjNoName = Omit2; +>ObjNoName : Omit2 + +declare let objNoName: ObjNoName; +>objNoName : Omit2 + +objNoName.id; // should exist +>objNoName.id : number +>objNoName : Omit2 +>id : number + +objNoName.name; // should be removed +>objNoName.name : any +>objNoName : Omit2 +>name : any + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralMatching.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralMatching.errors.txt new file mode 100644 index 0000000000000..5cacf340b22b4 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralMatching.errors.txt @@ -0,0 +1,61 @@ +negatedTypesInPatternLiteralMatching.ts(10,1): error TS2322: Type '"foobar"' is not assignable to type '`foo${string & not "bar"}`'. +negatedTypesInPatternLiteralMatching.ts(12,1): error TS2322: Type '"baz"' is not assignable to type '`foo${string & not "bar"}`'. +negatedTypesInPatternLiteralMatching.ts(18,1): error TS2322: Type '"foobar"' is not assignable to type '`foo${string & not "bar"}`'. +negatedTypesInPatternLiteralMatching.ts(32,21): error TS2345: Argument of type '"foobar"' is not assignable to parameter of type 'never'. +negatedTypesInPatternLiteralMatching.ts(38,1): error TS2322: Type '"foobar"' is not assignable to type '`foo${string & not "bar" & not "qux"}`'. +negatedTypesInPatternLiteralMatching.ts(39,1): error TS2322: Type '"fooqux"' is not assignable to type '`foo${string & not "bar" & not "qux"}`'. + + +==== negatedTypesInPatternLiteralMatching.ts (6 errors) ==== + // Matching actual string literal types against pattern literal types that + // contain negated holes. `"foobaz"` should match `foo${string & not "bar"}` + // but `"foobar"` should not, because the hole excludes exactly "bar". + + type Pattern = `foo${string & not "bar"}`; + + // Direct assignment of literals to the pattern type. + declare let pat: Pattern; + pat = "foobaz"; // should be ok + pat = "foobar"; // should error + ~~~ +!!! error TS2322: Type '"foobar"' is not assignable to type '`foo${string & not "bar"}`'. + pat = "foo"; // should be ok (the hole can match the empty string) + pat = "baz"; // should error (missing "foo" prefix) + ~~~ +!!! error TS2322: Type '"baz"' is not assignable to type '`foo${string & not "bar"}`'. + + // Assignability from a literal-typed value. + declare const foobaz: "foobaz"; + declare const foobar: "foobar"; + pat = foobaz; // should be ok + pat = foobar; // should error + ~~~ +!!! error TS2322: Type '"foobar"' is not assignable to type '`foo${string & not "bar"}`'. + + // Matching via a conditional type (extends check). + type MatchFoobaz = "foobaz" extends Pattern ? true : false; // should be true + type MatchFoobar = "foobar" extends Pattern ? true : false; // should be false + + // Matching a union of literals: only the members that don't collapse the hole + // to never should be retained. + type FilterMatches = T extends Pattern ? T : never; + type Filtered = FilterMatches<"foobaz" | "foobar" | "fooqux">; // should be "foobaz" | "fooqux" + + // Inference through a generic function whose parameter is the pattern. + declare function take(s: `foo${T & not "bar"}`): T; + const okBaz = take("foobaz"); // should be ok, T = "baz" + const errBar = take("foobar"); // should error, "bar" is excluded + ~~~~~~~~ +!!! error TS2345: Argument of type '"foobar"' is not assignable to parameter of type 'never'. + + // Excluding a union of holes. + type Pattern2 = `foo${string & not ("bar" | "qux")}`; + declare let pat2: Pattern2; + pat2 = "foobaz"; // should be ok + pat2 = "foobar"; // should error + ~~~~ +!!! error TS2322: Type '"foobar"' is not assignable to type '`foo${string & not "bar" & not "qux"}`'. + pat2 = "fooqux"; // should error + ~~~~ +!!! error TS2322: Type '"fooqux"' is not assignable to type '`foo${string & not "bar" & not "qux"}`'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralMatching.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralMatching.symbols new file mode 100644 index 0000000000000..94ae61ca42913 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralMatching.symbols @@ -0,0 +1,97 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInPatternLiteralMatching.ts] //// + +=== negatedTypesInPatternLiteralMatching.ts === +// Matching actual string literal types against pattern literal types that +// contain negated holes. `"foobaz"` should match `foo${string & not "bar"}` +// but `"foobar"` should not, because the hole excludes exactly "bar". + +type Pattern = `foo${string & not "bar"}`; +>Pattern : Symbol(Pattern, Decl(negatedTypesInPatternLiteralMatching.ts, 0, 0)) + +// Direct assignment of literals to the pattern type. +declare let pat: Pattern; +>pat : Symbol(pat, Decl(negatedTypesInPatternLiteralMatching.ts, 7, 11)) +>Pattern : Symbol(Pattern, Decl(negatedTypesInPatternLiteralMatching.ts, 0, 0)) + +pat = "foobaz"; // should be ok +>pat : Symbol(pat, Decl(negatedTypesInPatternLiteralMatching.ts, 7, 11)) + +pat = "foobar"; // should error +>pat : Symbol(pat, Decl(negatedTypesInPatternLiteralMatching.ts, 7, 11)) + +pat = "foo"; // should be ok (the hole can match the empty string) +>pat : Symbol(pat, Decl(negatedTypesInPatternLiteralMatching.ts, 7, 11)) + +pat = "baz"; // should error (missing "foo" prefix) +>pat : Symbol(pat, Decl(negatedTypesInPatternLiteralMatching.ts, 7, 11)) + +// Assignability from a literal-typed value. +declare const foobaz: "foobaz"; +>foobaz : Symbol(foobaz, Decl(negatedTypesInPatternLiteralMatching.ts, 14, 13)) + +declare const foobar: "foobar"; +>foobar : Symbol(foobar, Decl(negatedTypesInPatternLiteralMatching.ts, 15, 13)) + +pat = foobaz; // should be ok +>pat : Symbol(pat, Decl(negatedTypesInPatternLiteralMatching.ts, 7, 11)) +>foobaz : Symbol(foobaz, Decl(negatedTypesInPatternLiteralMatching.ts, 14, 13)) + +pat = foobar; // should error +>pat : Symbol(pat, Decl(negatedTypesInPatternLiteralMatching.ts, 7, 11)) +>foobar : Symbol(foobar, Decl(negatedTypesInPatternLiteralMatching.ts, 15, 13)) + +// Matching via a conditional type (extends check). +type MatchFoobaz = "foobaz" extends Pattern ? true : false; // should be true +>MatchFoobaz : Symbol(MatchFoobaz, Decl(negatedTypesInPatternLiteralMatching.ts, 17, 13)) +>Pattern : Symbol(Pattern, Decl(negatedTypesInPatternLiteralMatching.ts, 0, 0)) + +type MatchFoobar = "foobar" extends Pattern ? true : false; // should be false +>MatchFoobar : Symbol(MatchFoobar, Decl(negatedTypesInPatternLiteralMatching.ts, 20, 59)) +>Pattern : Symbol(Pattern, Decl(negatedTypesInPatternLiteralMatching.ts, 0, 0)) + +// Matching a union of literals: only the members that don't collapse the hole +// to never should be retained. +type FilterMatches = T extends Pattern ? T : never; +>FilterMatches : Symbol(FilterMatches, Decl(negatedTypesInPatternLiteralMatching.ts, 21, 59)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralMatching.ts, 25, 19)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralMatching.ts, 25, 19)) +>Pattern : Symbol(Pattern, Decl(negatedTypesInPatternLiteralMatching.ts, 0, 0)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralMatching.ts, 25, 19)) + +type Filtered = FilterMatches<"foobaz" | "foobar" | "fooqux">; // should be "foobaz" | "fooqux" +>Filtered : Symbol(Filtered, Decl(negatedTypesInPatternLiteralMatching.ts, 25, 54)) +>FilterMatches : Symbol(FilterMatches, Decl(negatedTypesInPatternLiteralMatching.ts, 21, 59)) + +// Inference through a generic function whose parameter is the pattern. +declare function take(s: `foo${T & not "bar"}`): T; +>take : Symbol(take, Decl(negatedTypesInPatternLiteralMatching.ts, 26, 62)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralMatching.ts, 29, 22)) +>s : Symbol(s, Decl(negatedTypesInPatternLiteralMatching.ts, 29, 40)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralMatching.ts, 29, 22)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralMatching.ts, 29, 22)) + +const okBaz = take("foobaz"); // should be ok, T = "baz" +>okBaz : Symbol(okBaz, Decl(negatedTypesInPatternLiteralMatching.ts, 30, 5)) +>take : Symbol(take, Decl(negatedTypesInPatternLiteralMatching.ts, 26, 62)) + +const errBar = take("foobar"); // should error, "bar" is excluded +>errBar : Symbol(errBar, Decl(negatedTypesInPatternLiteralMatching.ts, 31, 5)) +>take : Symbol(take, Decl(negatedTypesInPatternLiteralMatching.ts, 26, 62)) + +// Excluding a union of holes. +type Pattern2 = `foo${string & not ("bar" | "qux")}`; +>Pattern2 : Symbol(Pattern2, Decl(negatedTypesInPatternLiteralMatching.ts, 31, 30)) + +declare let pat2: Pattern2; +>pat2 : Symbol(pat2, Decl(negatedTypesInPatternLiteralMatching.ts, 35, 11)) +>Pattern2 : Symbol(Pattern2, Decl(negatedTypesInPatternLiteralMatching.ts, 31, 30)) + +pat2 = "foobaz"; // should be ok +>pat2 : Symbol(pat2, Decl(negatedTypesInPatternLiteralMatching.ts, 35, 11)) + +pat2 = "foobar"; // should error +>pat2 : Symbol(pat2, Decl(negatedTypesInPatternLiteralMatching.ts, 35, 11)) + +pat2 = "fooqux"; // should error +>pat2 : Symbol(pat2, Decl(negatedTypesInPatternLiteralMatching.ts, 35, 11)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralMatching.types b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralMatching.types new file mode 100644 index 0000000000000..10447569d6d61 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralMatching.types @@ -0,0 +1,109 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInPatternLiteralMatching.ts] //// + +=== negatedTypesInPatternLiteralMatching.ts === +// Matching actual string literal types against pattern literal types that +// contain negated holes. `"foobaz"` should match `foo${string & not "bar"}` +// but `"foobar"` should not, because the hole excludes exactly "bar". + +type Pattern = `foo${string & not "bar"}`; +>Pattern : `foo${string & not "bar"}` + +// Direct assignment of literals to the pattern type. +declare let pat: Pattern; +>pat : `foo${string & not "bar"}` + +pat = "foobaz"; // should be ok +>pat = "foobaz" : "foobaz" +>pat : `foo${string & not "bar"}` +>"foobaz" : "foobaz" + +pat = "foobar"; // should error +>pat = "foobar" : "foobar" +>pat : `foo${string & not "bar"}` +>"foobar" : "foobar" + +pat = "foo"; // should be ok (the hole can match the empty string) +>pat = "foo" : "foo" +>pat : `foo${string & not "bar"}` +>"foo" : "foo" + +pat = "baz"; // should error (missing "foo" prefix) +>pat = "baz" : "baz" +>pat : `foo${string & not "bar"}` +>"baz" : "baz" + +// Assignability from a literal-typed value. +declare const foobaz: "foobaz"; +>foobaz : "foobaz" + +declare const foobar: "foobar"; +>foobar : "foobar" + +pat = foobaz; // should be ok +>pat = foobaz : "foobaz" +>pat : `foo${string & not "bar"}` +>foobaz : "foobaz" + +pat = foobar; // should error +>pat = foobar : "foobar" +>pat : `foo${string & not "bar"}` +>foobar : "foobar" + +// Matching via a conditional type (extends check). +type MatchFoobaz = "foobaz" extends Pattern ? true : false; // should be true +>MatchFoobaz : true +>true : true +>false : false + +type MatchFoobar = "foobar" extends Pattern ? true : false; // should be false +>MatchFoobar : false +>true : true +>false : false + +// Matching a union of literals: only the members that don't collapse the hole +// to never should be retained. +type FilterMatches = T extends Pattern ? T : never; +>FilterMatches : FilterMatches + +type Filtered = FilterMatches<"foobaz" | "foobar" | "fooqux">; // should be "foobaz" | "fooqux" +>Filtered : Filtered + +// Inference through a generic function whose parameter is the pattern. +declare function take(s: `foo${T & not "bar"}`): T; +>take : (s: `foo${T & not "bar"}`) => T +>s : `foo${T & not "bar"}` + +const okBaz = take("foobaz"); // should be ok, T = "baz" +>okBaz : "baz" +>take("foobaz") : "baz" +>take : (s: `foo${T & not "bar"}`) => T +>"foobaz" : "foobaz" + +const errBar = take("foobar"); // should error, "bar" is excluded +>errBar : "bar" +>take("foobar") : "bar" +>take : (s: `foo${T & not "bar"}`) => T +>"foobar" : "foobar" + +// Excluding a union of holes. +type Pattern2 = `foo${string & not ("bar" | "qux")}`; +>Pattern2 : `foo${string & not "bar" & not "qux"}` + +declare let pat2: Pattern2; +>pat2 : `foo${string & not "bar" & not "qux"}` + +pat2 = "foobaz"; // should be ok +>pat2 = "foobaz" : "foobaz" +>pat2 : `foo${string & not "bar" & not "qux"}` +>"foobaz" : "foobaz" + +pat2 = "foobar"; // should error +>pat2 = "foobar" : "foobar" +>pat2 : `foo${string & not "bar" & not "qux"}` +>"foobar" : "foobar" + +pat2 = "fooqux"; // should error +>pat2 = "fooqux" : "fooqux" +>pat2 : `foo${string & not "bar" & not "qux"}` +>"fooqux" : "fooqux" + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiterals.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiterals.errors.txt new file mode 100644 index 0000000000000..166406674d4e3 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiterals.errors.txt @@ -0,0 +1,68 @@ +negatedTypesInPatternLiterals.ts(4,21): error TS2322: Type 'not "bar"' is not assignable to type 'string | number | bigint | boolean | null | undefined'. + Type 'unknown' is not assignable to type 'string | number | bigint | boolean | null | undefined'. +negatedTypesInPatternLiterals.ts(7,24): error TS2322: Type 'not string' is not assignable to type 'string | number | bigint | boolean | null | undefined'. + Type 'unknown' is not assignable to type 'string | number | bigint | boolean | null | undefined'. +negatedTypesInPatternLiterals.ts(8,24): error TS2322: Type 'not 0' is not assignable to type 'string | number | bigint | boolean | null | undefined'. + Type 'unknown' is not assignable to type 'string | number | bigint | boolean | null | undefined'. +negatedTypesInPatternLiterals.ts(11,19): error TS2322: Type 'not "a" & not "b"' is not assignable to type 'string | number | bigint | boolean | null | undefined'. +negatedTypesInPatternLiterals.ts(17,22): error TS2322: Type 'T & not "bar"' is not assignable to type 'string | number | bigint | boolean | null | undefined'. +negatedTypesInPatternLiterals.ts(27,1): error TS2322: Type 'string' is not assignable to type '`foo${not "bar"}`'. +negatedTypesInPatternLiterals.ts(29,1): error TS2322: Type '"foobar"' is not assignable to type '`foo${string & not "bar"}`'. +negatedTypesInPatternLiterals.ts(34,18): error TS2345: Argument of type '"foobar"' is not assignable to parameter of type 'never'. + + +==== negatedTypesInPatternLiterals.ts (8 errors) ==== + // Negated types used as placeholders inside template/pattern literal types. + + // A negated string literal as a placeholder. + type NotBar = `foo${not "bar"}`; + ~~~~~~~~~ +!!! error TS2322: Type 'not "bar"' is not assignable to type 'string | number | bigint | boolean | null | undefined'. +!!! error TS2322: Type 'unknown' is not assignable to type 'string | number | bigint | boolean | null | undefined'. + + // A negated primitive as a placeholder. + type NotString = `foo${not string}`; + ~~~~~~~~~~ +!!! error TS2322: Type 'not string' is not assignable to type 'string | number | bigint | boolean | null | undefined'. +!!! error TS2322: Type 'unknown' is not assignable to type 'string | number | bigint | boolean | null | undefined'. + type NotNumber = `id-${not 0}`; + ~~~~~ +!!! error TS2322: Type 'not 0' is not assignable to type 'string | number | bigint | boolean | null | undefined'. +!!! error TS2322: Type 'unknown' is not assignable to type 'string | number | bigint | boolean | null | undefined'. + + // A negated union as a placeholder. + type NotAB = `x-${not ("a" | "b")}`; + ~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'not "a" & not "b"' is not assignable to type 'string | number | bigint | boolean | null | undefined'. + + // A negated type intersected with a string, which restricts to string values. + type StringNotBar = `foo${string & not "bar"}`; + + // A generic negated placeholder. + type Wrap = `foo${T & not "bar"}`; + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'T & not "bar"' is not assignable to type 'string | number | bigint | boolean | null | undefined'. + type WrapString = Wrap; + type WrapLiteral = Wrap<"baz">; + type WrapBar = Wrap<"bar">; + + // Assignability against a plainly-typed string. + declare let notBar: NotBar; + declare let stringNotBar: StringNotBar; + + notBar = "foobaz"; // depends on representation + notBar = "foobar"; // depends on representation + ~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type '`foo${not "bar"}`'. + stringNotBar = "foobaz"; // depends on representation + stringNotBar = "foobar"; // depends on representation + ~~~~~~~~~~~~ +!!! error TS2322: Type '"foobar"' is not assignable to type '`foo${string & not "bar"}`'. + + // Inference from a template literal pattern with a negated placeholder. + declare function parse(s: `foo${T & not "bar"}`): T; + const p1 = parse("foobaz"); + const p2 = parse("foobar"); + ~~~~~~~~ +!!! error TS2345: Argument of type '"foobar"' is not assignable to parameter of type 'never'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiterals.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiterals.symbols new file mode 100644 index 0000000000000..623abd52bfec2 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiterals.symbols @@ -0,0 +1,79 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInPatternLiterals.ts] //// + +=== negatedTypesInPatternLiterals.ts === +// Negated types used as placeholders inside template/pattern literal types. + +// A negated string literal as a placeholder. +type NotBar = `foo${not "bar"}`; +>NotBar : Symbol(NotBar, Decl(negatedTypesInPatternLiterals.ts, 0, 0)) + +// A negated primitive as a placeholder. +type NotString = `foo${not string}`; +>NotString : Symbol(NotString, Decl(negatedTypesInPatternLiterals.ts, 3, 32)) + +type NotNumber = `id-${not 0}`; +>NotNumber : Symbol(NotNumber, Decl(negatedTypesInPatternLiterals.ts, 6, 36)) + +// A negated union as a placeholder. +type NotAB = `x-${not ("a" | "b")}`; +>NotAB : Symbol(NotAB, Decl(negatedTypesInPatternLiterals.ts, 7, 31)) + +// A negated type intersected with a string, which restricts to string values. +type StringNotBar = `foo${string & not "bar"}`; +>StringNotBar : Symbol(StringNotBar, Decl(negatedTypesInPatternLiterals.ts, 10, 36)) + +// A generic negated placeholder. +type Wrap = `foo${T & not "bar"}`; +>Wrap : Symbol(Wrap, Decl(negatedTypesInPatternLiterals.ts, 13, 47)) +>T : Symbol(T, Decl(negatedTypesInPatternLiterals.ts, 16, 10)) +>T : Symbol(T, Decl(negatedTypesInPatternLiterals.ts, 16, 10)) + +type WrapString = Wrap; +>WrapString : Symbol(WrapString, Decl(negatedTypesInPatternLiterals.ts, 16, 37)) +>Wrap : Symbol(Wrap, Decl(negatedTypesInPatternLiterals.ts, 13, 47)) + +type WrapLiteral = Wrap<"baz">; +>WrapLiteral : Symbol(WrapLiteral, Decl(negatedTypesInPatternLiterals.ts, 17, 31)) +>Wrap : Symbol(Wrap, Decl(negatedTypesInPatternLiterals.ts, 13, 47)) + +type WrapBar = Wrap<"bar">; +>WrapBar : Symbol(WrapBar, Decl(negatedTypesInPatternLiterals.ts, 18, 31)) +>Wrap : Symbol(Wrap, Decl(negatedTypesInPatternLiterals.ts, 13, 47)) + +// Assignability against a plainly-typed string. +declare let notBar: NotBar; +>notBar : Symbol(notBar, Decl(negatedTypesInPatternLiterals.ts, 22, 11)) +>NotBar : Symbol(NotBar, Decl(negatedTypesInPatternLiterals.ts, 0, 0)) + +declare let stringNotBar: StringNotBar; +>stringNotBar : Symbol(stringNotBar, Decl(negatedTypesInPatternLiterals.ts, 23, 11)) +>StringNotBar : Symbol(StringNotBar, Decl(negatedTypesInPatternLiterals.ts, 10, 36)) + +notBar = "foobaz"; // depends on representation +>notBar : Symbol(notBar, Decl(negatedTypesInPatternLiterals.ts, 22, 11)) + +notBar = "foobar"; // depends on representation +>notBar : Symbol(notBar, Decl(negatedTypesInPatternLiterals.ts, 22, 11)) + +stringNotBar = "foobaz"; // depends on representation +>stringNotBar : Symbol(stringNotBar, Decl(negatedTypesInPatternLiterals.ts, 23, 11)) + +stringNotBar = "foobar"; // depends on representation +>stringNotBar : Symbol(stringNotBar, Decl(negatedTypesInPatternLiterals.ts, 23, 11)) + +// Inference from a template literal pattern with a negated placeholder. +declare function parse(s: `foo${T & not "bar"}`): T; +>parse : Symbol(parse, Decl(negatedTypesInPatternLiterals.ts, 28, 24)) +>T : Symbol(T, Decl(negatedTypesInPatternLiterals.ts, 31, 23)) +>s : Symbol(s, Decl(negatedTypesInPatternLiterals.ts, 31, 41)) +>T : Symbol(T, Decl(negatedTypesInPatternLiterals.ts, 31, 23)) +>T : Symbol(T, Decl(negatedTypesInPatternLiterals.ts, 31, 23)) + +const p1 = parse("foobaz"); +>p1 : Symbol(p1, Decl(negatedTypesInPatternLiterals.ts, 32, 5)) +>parse : Symbol(parse, Decl(negatedTypesInPatternLiterals.ts, 28, 24)) + +const p2 = parse("foobar"); +>p2 : Symbol(p2, Decl(negatedTypesInPatternLiterals.ts, 33, 5)) +>parse : Symbol(parse, Decl(negatedTypesInPatternLiterals.ts, 28, 24)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiterals.types b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiterals.types new file mode 100644 index 0000000000000..36845a2756d17 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiterals.types @@ -0,0 +1,81 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInPatternLiterals.ts] //// + +=== negatedTypesInPatternLiterals.ts === +// Negated types used as placeholders inside template/pattern literal types. + +// A negated string literal as a placeholder. +type NotBar = `foo${not "bar"}`; +>NotBar : `foo${not "bar"}` + +// A negated primitive as a placeholder. +type NotString = `foo${not string}`; +>NotString : `foo${not string}` + +type NotNumber = `id-${not 0}`; +>NotNumber : `id-${not 0}` + +// A negated union as a placeholder. +type NotAB = `x-${not ("a" | "b")}`; +>NotAB : `x-${not "a" & not "b"}` + +// A negated type intersected with a string, which restricts to string values. +type StringNotBar = `foo${string & not "bar"}`; +>StringNotBar : `foo${string & not "bar"}` + +// A generic negated placeholder. +type Wrap = `foo${T & not "bar"}`; +>Wrap : `foo${T & not "bar"}` + +type WrapString = Wrap; +>WrapString : `foo${string & not "bar"}` + +type WrapLiteral = Wrap<"baz">; +>WrapLiteral : "foobaz" + +type WrapBar = Wrap<"bar">; +>WrapBar : never + +// Assignability against a plainly-typed string. +declare let notBar: NotBar; +>notBar : `foo${not "bar"}` + +declare let stringNotBar: StringNotBar; +>stringNotBar : `foo${string & not "bar"}` + +notBar = "foobaz"; // depends on representation +>notBar = "foobaz" : "foobaz" +>notBar : `foo${not "bar"}` +>"foobaz" : "foobaz" + +notBar = "foobar"; // depends on representation +>notBar = "foobar" : "foobar" +>notBar : `foo${not "bar"}` +>"foobar" : "foobar" + +stringNotBar = "foobaz"; // depends on representation +>stringNotBar = "foobaz" : "foobaz" +>stringNotBar : `foo${string & not "bar"}` +>"foobaz" : "foobaz" + +stringNotBar = "foobar"; // depends on representation +>stringNotBar = "foobar" : "foobar" +>stringNotBar : `foo${string & not "bar"}` +>"foobar" : "foobar" + +// Inference from a template literal pattern with a negated placeholder. +declare function parse(s: `foo${T & not "bar"}`): T; +>parse : (s: `foo${T & not "bar"}`) => T +>s : `foo${T & not "bar"}` + +const p1 = parse("foobaz"); +>p1 : "baz" +>parse("foobaz") : "baz" +>parse : (s: `foo${T & not "bar"}`) => T +>"foobaz" : "foobaz" + +const p2 = parse("foobar"); +>p2 : "bar" +>parse("foobar") : "bar" +>parse : (s: `foo${T & not "bar"}`) => T +>"foobar" : "foobar" + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndIndexSignatures.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndIndexSignatures.errors.txt new file mode 100644 index 0000000000000..f1036021e1aa0 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndIndexSignatures.errors.txt @@ -0,0 +1,48 @@ +negatedTypesInPatternLiteralsAndIndexSignatures.ts(10,1): error TS7053: Element implicitly has an 'any' type because expression of type '"foobar"' can't be used to index type 'TemplateKey'. + Property 'foobar' does not exist on type 'TemplateKey'. +negatedTypesInPatternLiteralsAndIndexSignatures.ts(11,1): error TS7053: Element implicitly has an 'any' type because expression of type '"baz"' can't be used to index type 'TemplateKey'. + Property 'baz' does not exist on type 'TemplateKey'. +negatedTypesInPatternLiteralsAndIndexSignatures.ts(15,6): error TS1268: An index signature parameter type must be 'string', 'number', 'symbol', or a template literal type. +negatedTypesInPatternLiteralsAndIndexSignatures.ts(25,6): error TS1337: An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead. + + +==== negatedTypesInPatternLiteralsAndIndexSignatures.ts (4 errors) ==== + // Combination: negated types with BOTH pattern literal types and index signatures. + + // Index signature whose key is a template literal containing a negated placeholder. + type TemplateKey = { + [idx: `foo${string & not "bar"}`]: number; + }; + + declare let templateKey: TemplateKey; + templateKey["foobaz"] = 1; // matches pattern + templateKey["foobar"] = 1; // excluded by negation + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type '"foobar"' can't be used to index type 'TemplateKey'. +!!! error TS7053: Property 'foobar' does not exist on type 'TemplateKey'. + templateKey["baz"] = 1; // does not match pattern + ~~~~~~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type '"baz"' can't be used to index type 'TemplateKey'. +!!! error TS7053: Property 'baz' does not exist on type 'TemplateKey'. + + // Index signature whose key is a bare negated template literal. + type NotTemplateKey = { + [idx: not `foo${string}`]: number; + ~~~ +!!! error TS1268: An index signature parameter type must be 'string', 'number', 'symbol', or a template literal type. + }; + + // Mapped type over a template literal key type that uses a negated placeholder. + type MappedTemplate = { + [k in `foo${string & not "bar"}`]: number; + }; + + // Generic index signature combination. + type WrapKey = { + [idx: `foo${T & not "bar"}`]: number; + ~~~ +!!! error TS1337: An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead. + }; + type WrapKeyString = WrapKey; + type WrapKeyLiteral = WrapKey<"baz">; + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndIndexSignatures.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndIndexSignatures.symbols new file mode 100644 index 0000000000000..ae1ec0b836b1c --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndIndexSignatures.symbols @@ -0,0 +1,63 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsAndIndexSignatures.ts] //// + +=== negatedTypesInPatternLiteralsAndIndexSignatures.ts === +// Combination: negated types with BOTH pattern literal types and index signatures. + +// Index signature whose key is a template literal containing a negated placeholder. +type TemplateKey = { +>TemplateKey : Symbol(TemplateKey, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 0, 0)) + + [idx: `foo${string & not "bar"}`]: number; +>idx : Symbol(idx, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 4, 5)) + +}; + +declare let templateKey: TemplateKey; +>templateKey : Symbol(templateKey, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 7, 11)) +>TemplateKey : Symbol(TemplateKey, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 0, 0)) + +templateKey["foobaz"] = 1; // matches pattern +>templateKey : Symbol(templateKey, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 7, 11)) + +templateKey["foobar"] = 1; // excluded by negation +>templateKey : Symbol(templateKey, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 7, 11)) + +templateKey["baz"] = 1; // does not match pattern +>templateKey : Symbol(templateKey, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 7, 11)) + +// Index signature whose key is a bare negated template literal. +type NotTemplateKey = { +>NotTemplateKey : Symbol(NotTemplateKey, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 10, 23)) + + [idx: not `foo${string}`]: number; +>idx : Symbol(idx, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 14, 5)) + +}; + +// Mapped type over a template literal key type that uses a negated placeholder. +type MappedTemplate = { +>MappedTemplate : Symbol(MappedTemplate, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 15, 2)) + + [k in `foo${string & not "bar"}`]: number; +>k : Symbol(k, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 19, 5)) + +}; + +// Generic index signature combination. +type WrapKey = { +>WrapKey : Symbol(WrapKey, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 20, 2)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 23, 13)) + + [idx: `foo${T & not "bar"}`]: number; +>idx : Symbol(idx, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 24, 5)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 23, 13)) + +}; +type WrapKeyString = WrapKey; +>WrapKeyString : Symbol(WrapKeyString, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 25, 2)) +>WrapKey : Symbol(WrapKey, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 20, 2)) + +type WrapKeyLiteral = WrapKey<"baz">; +>WrapKeyLiteral : Symbol(WrapKeyLiteral, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 26, 37)) +>WrapKey : Symbol(WrapKey, Decl(negatedTypesInPatternLiteralsAndIndexSignatures.ts, 20, 2)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndIndexSignatures.types b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndIndexSignatures.types new file mode 100644 index 0000000000000..73344ad71d105 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndIndexSignatures.types @@ -0,0 +1,68 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsAndIndexSignatures.ts] //// + +=== negatedTypesInPatternLiteralsAndIndexSignatures.ts === +// Combination: negated types with BOTH pattern literal types and index signatures. + +// Index signature whose key is a template literal containing a negated placeholder. +type TemplateKey = { +>TemplateKey : TemplateKey + + [idx: `foo${string & not "bar"}`]: number; +>idx : `foo${string & not "bar"}` + +}; + +declare let templateKey: TemplateKey; +>templateKey : TemplateKey + +templateKey["foobaz"] = 1; // matches pattern +>templateKey["foobaz"] = 1 : 1 +>templateKey["foobaz"] : number +>templateKey : TemplateKey +>"foobaz" : "foobaz" +>1 : 1 + +templateKey["foobar"] = 1; // excluded by negation +>templateKey["foobar"] = 1 : 1 +>templateKey["foobar"] : any +>templateKey : TemplateKey +>"foobar" : "foobar" +>1 : 1 + +templateKey["baz"] = 1; // does not match pattern +>templateKey["baz"] = 1 : 1 +>templateKey["baz"] : any +>templateKey : TemplateKey +>"baz" : "baz" +>1 : 1 + +// Index signature whose key is a bare negated template literal. +type NotTemplateKey = { +>NotTemplateKey : NotTemplateKey + + [idx: not `foo${string}`]: number; +>idx : not `foo${string}` + +}; + +// Mapped type over a template literal key type that uses a negated placeholder. +type MappedTemplate = { +>MappedTemplate : MappedTemplate + + [k in `foo${string & not "bar"}`]: number; +}; + +// Generic index signature combination. +type WrapKey = { +>WrapKey : WrapKey + + [idx: `foo${T & not "bar"}`]: number; +>idx : `foo${T & not "bar"}` + +}; +type WrapKeyString = WrapKey; +>WrapKeyString : WrapKeyString + +type WrapKeyLiteral = WrapKey<"baz">; +>WrapKeyLiteral : WrapKeyLiteral + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndStringMapping.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndStringMapping.errors.txt new file mode 100644 index 0000000000000..8ba3487201382 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndStringMapping.errors.txt @@ -0,0 +1,43 @@ +negatedTypesInPatternLiteralsAndStringMapping.ts(10,31): error TS2322: Type 'not "BAR"' is not assignable to type 'string | number | bigint | boolean | null | undefined'. + Type 'unknown' is not assignable to type 'string | number | bigint | boolean | null | undefined'. +negatedTypesInPatternLiteralsAndStringMapping.ts(26,1): error TS2322: Type '"foobaz"' is not assignable to type '`FOO${Uppercase<`${string & not "bar"}`>}`'. +negatedTypesInPatternLiteralsAndStringMapping.ts(28,1): error TS2322: Type '"foobar"' is not assignable to type '`foo${Uppercase<`${string & not "bar"}`>}`'. + + +==== negatedTypesInPatternLiteralsAndStringMapping.ts (3 errors) ==== + // Combination: negated types with BOTH pattern literal types and string mapping types. + + // String mapping wrapping a template literal that contains a negated placeholder. + type UpperTemplate = Uppercase<`foo${string & not "bar"}`>; + + // Template literal whose placeholder is a string mapping of a negated type. + type TemplateUpper = `foo${Uppercase}`; + + // Template literal whose placeholder is a negation of a string mapping type. + type TemplateNotUpper = `foo${not Uppercase<"BAR">}`; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'not "BAR"' is not assignable to type 'string | number | bigint | boolean | null | undefined'. +!!! error TS2322: Type 'unknown' is not assignable to type 'string | number | bigint | boolean | null | undefined'. + + // Negation of a template literal that contains a string mapping placeholder. + type NotTemplateUpper = not `foo${Uppercase}`; + + // Generic composition. + type Compose = Uppercase<`foo${T & not "bar"}`>; + type ComposeString = Compose; + type ComposeLiteral = Compose<"baz">; + type ComposeBar = Compose<"bar">; + + // Assignability probes. + declare let upperTemplate: UpperTemplate; + declare let templateUpper: TemplateUpper; + + upperTemplate = "FOOBAZ"; // depends on representation + upperTemplate = "foobaz"; // depends on representation + ~~~~~~~~~~~~~ +!!! error TS2322: Type '"foobaz"' is not assignable to type '`FOO${Uppercase<`${string & not "bar"}`>}`'. + templateUpper = "fooBAZ"; // depends on representation + templateUpper = "foobar"; // depends on representation + ~~~~~~~~~~~~~ +!!! error TS2322: Type '"foobar"' is not assignable to type '`foo${Uppercase<`${string & not "bar"}`>}`'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndStringMapping.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndStringMapping.symbols new file mode 100644 index 0000000000000..c47d35fb6a877 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndStringMapping.symbols @@ -0,0 +1,65 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsAndStringMapping.ts] //// + +=== negatedTypesInPatternLiteralsAndStringMapping.ts === +// Combination: negated types with BOTH pattern literal types and string mapping types. + +// String mapping wrapping a template literal that contains a negated placeholder. +type UpperTemplate = Uppercase<`foo${string & not "bar"}`>; +>UpperTemplate : Symbol(UpperTemplate, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 0, 0)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +// Template literal whose placeholder is a string mapping of a negated type. +type TemplateUpper = `foo${Uppercase}`; +>TemplateUpper : Symbol(TemplateUpper, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 3, 59)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +// Template literal whose placeholder is a negation of a string mapping type. +type TemplateNotUpper = `foo${not Uppercase<"BAR">}`; +>TemplateNotUpper : Symbol(TemplateNotUpper, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 6, 59)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +// Negation of a template literal that contains a string mapping placeholder. +type NotTemplateUpper = not `foo${Uppercase}`; +>NotTemplateUpper : Symbol(NotTemplateUpper, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 9, 53)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +// Generic composition. +type Compose = Uppercase<`foo${T & not "bar"}`>; +>Compose : Symbol(Compose, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 12, 54)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 15, 13)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 15, 13)) + +type ComposeString = Compose; +>ComposeString : Symbol(ComposeString, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 15, 66)) +>Compose : Symbol(Compose, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 12, 54)) + +type ComposeLiteral = Compose<"baz">; +>ComposeLiteral : Symbol(ComposeLiteral, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 16, 37)) +>Compose : Symbol(Compose, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 12, 54)) + +type ComposeBar = Compose<"bar">; +>ComposeBar : Symbol(ComposeBar, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 17, 37)) +>Compose : Symbol(Compose, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 12, 54)) + +// Assignability probes. +declare let upperTemplate: UpperTemplate; +>upperTemplate : Symbol(upperTemplate, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 21, 11)) +>UpperTemplate : Symbol(UpperTemplate, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 0, 0)) + +declare let templateUpper: TemplateUpper; +>templateUpper : Symbol(templateUpper, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 22, 11)) +>TemplateUpper : Symbol(TemplateUpper, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 3, 59)) + +upperTemplate = "FOOBAZ"; // depends on representation +>upperTemplate : Symbol(upperTemplate, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 21, 11)) + +upperTemplate = "foobaz"; // depends on representation +>upperTemplate : Symbol(upperTemplate, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 21, 11)) + +templateUpper = "fooBAZ"; // depends on representation +>templateUpper : Symbol(templateUpper, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 22, 11)) + +templateUpper = "foobar"; // depends on representation +>templateUpper : Symbol(templateUpper, Decl(negatedTypesInPatternLiteralsAndStringMapping.ts, 22, 11)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndStringMapping.types b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndStringMapping.types new file mode 100644 index 0000000000000..14151e20ae5a9 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsAndStringMapping.types @@ -0,0 +1,61 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsAndStringMapping.ts] //// + +=== negatedTypesInPatternLiteralsAndStringMapping.ts === +// Combination: negated types with BOTH pattern literal types and string mapping types. + +// String mapping wrapping a template literal that contains a negated placeholder. +type UpperTemplate = Uppercase<`foo${string & not "bar"}`>; +>UpperTemplate : `FOO${Uppercase<`${string & not "bar"}`>}` + +// Template literal whose placeholder is a string mapping of a negated type. +type TemplateUpper = `foo${Uppercase}`; +>TemplateUpper : `foo${Uppercase<`${string & not "bar"}`>}` + +// Template literal whose placeholder is a negation of a string mapping type. +type TemplateNotUpper = `foo${not Uppercase<"BAR">}`; +>TemplateNotUpper : `foo${not "BAR"}` + +// Negation of a template literal that contains a string mapping placeholder. +type NotTemplateUpper = not `foo${Uppercase}`; +>NotTemplateUpper : not `foo${Uppercase}` + +// Generic composition. +type Compose = Uppercase<`foo${T & not "bar"}`>; +>Compose : `FOO${Uppercase}` + +type ComposeString = Compose; +>ComposeString : `FOO${Uppercase<`${string & not "bar"}`>}` + +type ComposeLiteral = Compose<"baz">; +>ComposeLiteral : "FOOBAZ" + +type ComposeBar = Compose<"bar">; +>ComposeBar : never + +// Assignability probes. +declare let upperTemplate: UpperTemplate; +>upperTemplate : `FOO${Uppercase<`${string & not "bar"}`>}` + +declare let templateUpper: TemplateUpper; +>templateUpper : `foo${Uppercase<`${string & not "bar"}`>}` + +upperTemplate = "FOOBAZ"; // depends on representation +>upperTemplate = "FOOBAZ" : "FOOBAZ" +>upperTemplate : `FOO${Uppercase<`${string & not "bar"}`>}` +>"FOOBAZ" : "FOOBAZ" + +upperTemplate = "foobaz"; // depends on representation +>upperTemplate = "foobaz" : "foobaz" +>upperTemplate : `FOO${Uppercase<`${string & not "bar"}`>}` +>"foobaz" : "foobaz" + +templateUpper = "fooBAZ"; // depends on representation +>templateUpper = "fooBAZ" : "fooBAZ" +>templateUpper : `foo${Uppercase<`${string & not "bar"}`>}` +>"fooBAZ" : "fooBAZ" + +templateUpper = "foobar"; // depends on representation +>templateUpper = "foobar" : "foobar" +>templateUpper : `foo${Uppercase<`${string & not "bar"}`>}` +>"foobar" : "foobar" + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.errors.txt new file mode 100644 index 0000000000000..c9ac79abb34f7 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.errors.txt @@ -0,0 +1,49 @@ +negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts(10,1): error TS7053: Element implicitly has an 'any' type because expression of type '"foobaz"' can't be used to index type 'AllCombined'. + Property 'foobaz' does not exist on type 'AllCombined'. +negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts(20,1): error TS7053: Element implicitly has an 'any' type because expression of type '"foobaz"' can't be used to index type 'AllCombined2'. + Property 'foobaz' does not exist on type 'AllCombined2'. +negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts(29,6): error TS1337: An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead. + + +==== negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts (3 errors) ==== + // Combination: negated types with pattern literal types, string mapping types, AND index signatures. + + // Index signature whose key is a string mapping of a template literal containing a negated placeholder. + type AllCombined = { + [idx: Uppercase<`foo${string & not "bar"}`>]: number; + }; + + declare let allCombined: AllCombined; + allCombined["FOOBAZ"] = 1; // depends on representation + allCombined["foobaz"] = 1; // depends on representation + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type '"foobaz"' can't be used to index type 'AllCombined'. +!!! error TS7053: Property 'foobaz' does not exist on type 'AllCombined'. + allCombined["FOOBAR"] = 1; // depends on representation + + // Index signature whose key is a template literal whose placeholder is a string mapping of a negated type. + type AllCombined2 = { + [idx: `foo${Uppercase}`]: number; + }; + + declare let allCombined2: AllCombined2; + allCombined2["fooBAZ"] = 1; // depends on representation + allCombined2["foobaz"] = 1; // depends on representation + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type '"foobaz"' can't be used to index type 'AllCombined2'. +!!! error TS7053: Property 'foobaz' does not exist on type 'AllCombined2'. + + // Mapped type form combining all three. + type MappedAll = { + [k in Uppercase<`foo${string & not "bar"}`>]: number; + }; + + // Generic composition of all three. + type WrapAll = { + [idx: Uppercase<`foo${T & not "bar"}`>]: number; + ~~~ +!!! error TS1337: An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead. + }; + type WrapAllString = WrapAll; + type WrapAllLiteral = WrapAll<"baz">; + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.symbols new file mode 100644 index 0000000000000..271995f37858a --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.symbols @@ -0,0 +1,77 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts] //// + +=== negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts === +// Combination: negated types with pattern literal types, string mapping types, AND index signatures. + +// Index signature whose key is a string mapping of a template literal containing a negated placeholder. +type AllCombined = { +>AllCombined : Symbol(AllCombined, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 0, 0)) + + [idx: Uppercase<`foo${string & not "bar"}`>]: number; +>idx : Symbol(idx, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 4, 5)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +}; + +declare let allCombined: AllCombined; +>allCombined : Symbol(allCombined, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 7, 11)) +>AllCombined : Symbol(AllCombined, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 0, 0)) + +allCombined["FOOBAZ"] = 1; // depends on representation +>allCombined : Symbol(allCombined, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 7, 11)) + +allCombined["foobaz"] = 1; // depends on representation +>allCombined : Symbol(allCombined, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 7, 11)) + +allCombined["FOOBAR"] = 1; // depends on representation +>allCombined : Symbol(allCombined, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 7, 11)) + +// Index signature whose key is a template literal whose placeholder is a string mapping of a negated type. +type AllCombined2 = { +>AllCombined2 : Symbol(AllCombined2, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 10, 26)) + + [idx: `foo${Uppercase}`]: number; +>idx : Symbol(idx, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 14, 5)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +}; + +declare let allCombined2: AllCombined2; +>allCombined2 : Symbol(allCombined2, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 17, 11)) +>AllCombined2 : Symbol(AllCombined2, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 10, 26)) + +allCombined2["fooBAZ"] = 1; // depends on representation +>allCombined2 : Symbol(allCombined2, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 17, 11)) + +allCombined2["foobaz"] = 1; // depends on representation +>allCombined2 : Symbol(allCombined2, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 17, 11)) + +// Mapped type form combining all three. +type MappedAll = { +>MappedAll : Symbol(MappedAll, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 19, 27)) + + [k in Uppercase<`foo${string & not "bar"}`>]: number; +>k : Symbol(k, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 23, 5)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +}; + +// Generic composition of all three. +type WrapAll = { +>WrapAll : Symbol(WrapAll, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 24, 2)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 27, 13)) + + [idx: Uppercase<`foo${T & not "bar"}`>]: number; +>idx : Symbol(idx, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 28, 5)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 27, 13)) + +}; +type WrapAllString = WrapAll; +>WrapAllString : Symbol(WrapAllString, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 29, 2)) +>WrapAll : Symbol(WrapAll, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 24, 2)) + +type WrapAllLiteral = WrapAll<"baz">; +>WrapAllLiteral : Symbol(WrapAllLiteral, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 30, 37)) +>WrapAll : Symbol(WrapAll, Decl(negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts, 24, 2)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.types b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.types new file mode 100644 index 0000000000000..a861cfa9ef5a6 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.types @@ -0,0 +1,85 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts] //// + +=== negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts === +// Combination: negated types with pattern literal types, string mapping types, AND index signatures. + +// Index signature whose key is a string mapping of a template literal containing a negated placeholder. +type AllCombined = { +>AllCombined : AllCombined + + [idx: Uppercase<`foo${string & not "bar"}`>]: number; +>idx : `FOO${Uppercase<`${string & not "bar"}`>}` + +}; + +declare let allCombined: AllCombined; +>allCombined : AllCombined + +allCombined["FOOBAZ"] = 1; // depends on representation +>allCombined["FOOBAZ"] = 1 : 1 +>allCombined["FOOBAZ"] : number +>allCombined : AllCombined +>"FOOBAZ" : "FOOBAZ" +>1 : 1 + +allCombined["foobaz"] = 1; // depends on representation +>allCombined["foobaz"] = 1 : 1 +>allCombined["foobaz"] : any +>allCombined : AllCombined +>"foobaz" : "foobaz" +>1 : 1 + +allCombined["FOOBAR"] = 1; // depends on representation +>allCombined["FOOBAR"] = 1 : 1 +>allCombined["FOOBAR"] : number +>allCombined : AllCombined +>"FOOBAR" : "FOOBAR" +>1 : 1 + +// Index signature whose key is a template literal whose placeholder is a string mapping of a negated type. +type AllCombined2 = { +>AllCombined2 : AllCombined2 + + [idx: `foo${Uppercase}`]: number; +>idx : `foo${Uppercase<`${string & not "bar"}`>}` + +}; + +declare let allCombined2: AllCombined2; +>allCombined2 : AllCombined2 + +allCombined2["fooBAZ"] = 1; // depends on representation +>allCombined2["fooBAZ"] = 1 : 1 +>allCombined2["fooBAZ"] : number +>allCombined2 : AllCombined2 +>"fooBAZ" : "fooBAZ" +>1 : 1 + +allCombined2["foobaz"] = 1; // depends on representation +>allCombined2["foobaz"] = 1 : 1 +>allCombined2["foobaz"] : any +>allCombined2 : AllCombined2 +>"foobaz" : "foobaz" +>1 : 1 + +// Mapped type form combining all three. +type MappedAll = { +>MappedAll : MappedAll + + [k in Uppercase<`foo${string & not "bar"}`>]: number; +}; + +// Generic composition of all three. +type WrapAll = { +>WrapAll : WrapAll + + [idx: Uppercase<`foo${T & not "bar"}`>]: number; +>idx : `FOO${Uppercase}` + +}; +type WrapAllString = WrapAll; +>WrapAllString : WrapAllString + +type WrapAllLiteral = WrapAll<"baz">; +>WrapAllLiteral : WrapAllLiteral + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMapping.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMapping.errors.txt new file mode 100644 index 0000000000000..bb84f5a79a123 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMapping.errors.txt @@ -0,0 +1,54 @@ +negatedTypesInStringMapping.ts(4,21): error TS2344: Type 'not "bar"' does not satisfy the constraint 'string'. + Type 'unknown' is not assignable to type 'string'. +negatedTypesInStringMapping.ts(5,21): error TS2344: Type 'not string' does not satisfy the constraint 'string'. + Type 'unknown' is not assignable to type 'string'. +negatedTypesInStringMapping.ts(6,21): error TS2344: Type 'not "a" & not "b"' does not satisfy the constraint 'string'. +negatedTypesInStringMapping.ts(28,1): error TS2322: Type 'string' is not assignable to type 'Uppercase<`${not "bar"}`>'. +negatedTypesInStringMapping.ts(31,1): error TS2322: Type 'string' is not assignable to type 'not "BAR"'. + + +==== negatedTypesInStringMapping.ts (5 errors) ==== + // Negated types used with intrinsic string mapping types. + + // Uppercase applied to a negated type: `Uppercase`. + type U1 = Uppercase; + ~~~~~~~~~ +!!! error TS2344: Type 'not "bar"' does not satisfy the constraint 'string'. +!!! error TS2344: Type 'unknown' is not assignable to type 'string'. + type U2 = Uppercase; + ~~~~~~~~~~ +!!! error TS2344: Type 'not string' does not satisfy the constraint 'string'. +!!! error TS2344: Type 'unknown' is not assignable to type 'string'. + type U3 = Uppercase; + ~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'not "a" & not "b"' does not satisfy the constraint 'string'. + type U4 = Uppercase; + + // Negation applied to a string mapping type: `not Uppercase`. + type N1 = not Uppercase<"bar">; + type N2 = not Uppercase; + type N3 = not Lowercase<"ABC">; + + // Generic forms. + type MapUpper = Uppercase; + type MapUpperString = MapUpper; + type MapUpperLiteral = MapUpper<"baz">; + + type NegUpper = not Uppercase; + type NegUpperString = NegUpper; + type NegUpperLiteral = NegUpper<"baz">; + + // Assignability probes. + declare let u1: U1; + declare let n1: N1; + + u1 = "BAZ"; // depends on representation + u1 = "baz"; // depends on representation + ~~ +!!! error TS2322: Type 'string' is not assignable to type 'Uppercase<`${not "bar"}`>'. + + n1 = "baz"; // depends on representation + n1 = "BAR"; // depends on representation + ~~ +!!! error TS2322: Type 'string' is not assignable to type 'not "BAR"'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMapping.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMapping.symbols new file mode 100644 index 0000000000000..d27ed6693b180 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMapping.symbols @@ -0,0 +1,85 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInStringMapping.ts] //// + +=== negatedTypesInStringMapping.ts === +// Negated types used with intrinsic string mapping types. + +// Uppercase applied to a negated type: `Uppercase`. +type U1 = Uppercase; +>U1 : Symbol(U1, Decl(negatedTypesInStringMapping.ts, 0, 0)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +type U2 = Uppercase; +>U2 : Symbol(U2, Decl(negatedTypesInStringMapping.ts, 3, 31)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +type U3 = Uppercase; +>U3 : Symbol(U3, Decl(negatedTypesInStringMapping.ts, 4, 32)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +type U4 = Uppercase; +>U4 : Symbol(U4, Decl(negatedTypesInStringMapping.ts, 5, 37)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +// Negation applied to a string mapping type: `not Uppercase`. +type N1 = not Uppercase<"bar">; +>N1 : Symbol(N1, Decl(negatedTypesInStringMapping.ts, 6, 40)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +type N2 = not Uppercase; +>N2 : Symbol(N2, Decl(negatedTypesInStringMapping.ts, 9, 31)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +type N3 = not Lowercase<"ABC">; +>N3 : Symbol(N3, Decl(negatedTypesInStringMapping.ts, 10, 32)) +>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --)) + +// Generic forms. +type MapUpper = Uppercase; +>MapUpper : Symbol(MapUpper, Decl(negatedTypesInStringMapping.ts, 11, 31)) +>T : Symbol(T, Decl(negatedTypesInStringMapping.ts, 14, 14)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(negatedTypesInStringMapping.ts, 14, 14)) + +type MapUpperString = MapUpper; +>MapUpperString : Symbol(MapUpperString, Decl(negatedTypesInStringMapping.ts, 14, 59)) +>MapUpper : Symbol(MapUpper, Decl(negatedTypesInStringMapping.ts, 11, 31)) + +type MapUpperLiteral = MapUpper<"baz">; +>MapUpperLiteral : Symbol(MapUpperLiteral, Decl(negatedTypesInStringMapping.ts, 15, 39)) +>MapUpper : Symbol(MapUpper, Decl(negatedTypesInStringMapping.ts, 11, 31)) + +type NegUpper = not Uppercase; +>NegUpper : Symbol(NegUpper, Decl(negatedTypesInStringMapping.ts, 16, 39)) +>T : Symbol(T, Decl(negatedTypesInStringMapping.ts, 18, 14)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(negatedTypesInStringMapping.ts, 18, 14)) + +type NegUpperString = NegUpper; +>NegUpperString : Symbol(NegUpperString, Decl(negatedTypesInStringMapping.ts, 18, 51)) +>NegUpper : Symbol(NegUpper, Decl(negatedTypesInStringMapping.ts, 16, 39)) + +type NegUpperLiteral = NegUpper<"baz">; +>NegUpperLiteral : Symbol(NegUpperLiteral, Decl(negatedTypesInStringMapping.ts, 19, 39)) +>NegUpper : Symbol(NegUpper, Decl(negatedTypesInStringMapping.ts, 16, 39)) + +// Assignability probes. +declare let u1: U1; +>u1 : Symbol(u1, Decl(negatedTypesInStringMapping.ts, 23, 11)) +>U1 : Symbol(U1, Decl(negatedTypesInStringMapping.ts, 0, 0)) + +declare let n1: N1; +>n1 : Symbol(n1, Decl(negatedTypesInStringMapping.ts, 24, 11)) +>N1 : Symbol(N1, Decl(negatedTypesInStringMapping.ts, 6, 40)) + +u1 = "BAZ"; // depends on representation +>u1 : Symbol(u1, Decl(negatedTypesInStringMapping.ts, 23, 11)) + +u1 = "baz"; // depends on representation +>u1 : Symbol(u1, Decl(negatedTypesInStringMapping.ts, 23, 11)) + +n1 = "baz"; // depends on representation +>n1 : Symbol(n1, Decl(negatedTypesInStringMapping.ts, 24, 11)) + +n1 = "BAR"; // depends on representation +>n1 : Symbol(n1, Decl(negatedTypesInStringMapping.ts, 24, 11)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMapping.types b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMapping.types new file mode 100644 index 0000000000000..8ce0281388da0 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMapping.types @@ -0,0 +1,74 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInStringMapping.ts] //// + +=== negatedTypesInStringMapping.ts === +// Negated types used with intrinsic string mapping types. + +// Uppercase applied to a negated type: `Uppercase`. +type U1 = Uppercase; +>U1 : Uppercase<`${not "bar"}`> + +type U2 = Uppercase; +>U2 : Uppercase<`${not string}`> + +type U3 = Uppercase; +>U3 : Uppercase<`${not "a" & not "b"}`> + +type U4 = Uppercase; +>U4 : Uppercase<`${string & not "bar"}`> + +// Negation applied to a string mapping type: `not Uppercase`. +type N1 = not Uppercase<"bar">; +>N1 : not "BAR" + +type N2 = not Uppercase; +>N2 : not Uppercase + +type N3 = not Lowercase<"ABC">; +>N3 : not "abc" + +// Generic forms. +type MapUpper = Uppercase; +>MapUpper : Uppercase + +type MapUpperString = MapUpper; +>MapUpperString : Uppercase<`${string & not "bar"}`> + +type MapUpperLiteral = MapUpper<"baz">; +>MapUpperLiteral : "BAZ" + +type NegUpper = not Uppercase; +>NegUpper : not Uppercase + +type NegUpperString = NegUpper; +>NegUpperString : not Uppercase + +type NegUpperLiteral = NegUpper<"baz">; +>NegUpperLiteral : not "BAZ" + +// Assignability probes. +declare let u1: U1; +>u1 : Uppercase<`${not "bar"}`> + +declare let n1: N1; +>n1 : not "BAR" + +u1 = "BAZ"; // depends on representation +>u1 = "BAZ" : "BAZ" +>u1 : Uppercase<`${not "bar"}`> +>"BAZ" : "BAZ" + +u1 = "baz"; // depends on representation +>u1 = "baz" : "baz" +>u1 : Uppercase<`${not "bar"}`> +>"baz" : "baz" + +n1 = "baz"; // depends on representation +>n1 = "baz" : "baz" +>n1 : not "BAR" +>"baz" : "baz" + +n1 = "BAR"; // depends on representation +>n1 = "BAR" : "BAR" +>n1 : not "BAR" +>"BAR" : "BAR" + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMappingAndIndexSignatures.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMappingAndIndexSignatures.errors.txt new file mode 100644 index 0000000000000..7e7c78c1db444 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMappingAndIndexSignatures.errors.txt @@ -0,0 +1,48 @@ +negatedTypesInStringMappingAndIndexSignatures.ts(10,1): error TS7053: Element implicitly has an 'any' type because expression of type '"foo"' can't be used to index type 'UpperKey'. + Property 'foo' does not exist on type 'UpperKey'. +negatedTypesInStringMappingAndIndexSignatures.ts(19,1): error TS7053: Element implicitly has an 'any' type because expression of type '"FOO"' can't be used to index type 'NotUpperKey'. + Property 'FOO' does not exist on type 'NotUpperKey'. +negatedTypesInStringMappingAndIndexSignatures.ts(28,6): error TS1337: An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead. + + +==== negatedTypesInStringMappingAndIndexSignatures.ts (3 errors) ==== + // Combination: negated types with BOTH string mapping types and index signatures. + + // Index signature whose key is a string mapping of a negated type. + type UpperKey = { + [idx: Uppercase]: number; + }; + + declare let upperKey: UpperKey; + upperKey["FOO"] = 1; // depends on representation + upperKey["foo"] = 1; // depends on representation + ~~~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type '"foo"' can't be used to index type 'UpperKey'. +!!! error TS7053: Property 'foo' does not exist on type 'UpperKey'. + + // Index signature whose key is a negation of a string mapping type. + type NotUpperKey = { + [idx: string & not Uppercase]: number; + }; + + declare let notUpperKey: NotUpperKey; + notUpperKey["foo"] = 1; // depends on representation + notUpperKey["FOO"] = 1; // depends on representation + ~~~~~~~~~~~~~~~~~~ +!!! error TS7053: Element implicitly has an 'any' type because expression of type '"FOO"' can't be used to index type 'NotUpperKey'. +!!! error TS7053: Property 'FOO' does not exist on type 'NotUpperKey'. + + // Mapped type over a string-mapping key type that uses a negated placeholder. + type MappedUpper = { + [k in Uppercase]: number; + }; + + // Generic index signature combination. + type WrapUpperKey = { + [idx: Uppercase]: number; + ~~~ +!!! error TS1337: An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead. + }; + type WrapUpperKeyString = WrapUpperKey; + type WrapUpperKeyLiteral = WrapUpperKey<"baz">; + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMappingAndIndexSignatures.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMappingAndIndexSignatures.symbols new file mode 100644 index 0000000000000..92f2cf57a269e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMappingAndIndexSignatures.symbols @@ -0,0 +1,74 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInStringMappingAndIndexSignatures.ts] //// + +=== negatedTypesInStringMappingAndIndexSignatures.ts === +// Combination: negated types with BOTH string mapping types and index signatures. + +// Index signature whose key is a string mapping of a negated type. +type UpperKey = { +>UpperKey : Symbol(UpperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 0, 0)) + + [idx: Uppercase]: number; +>idx : Symbol(idx, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 4, 5)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +}; + +declare let upperKey: UpperKey; +>upperKey : Symbol(upperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 7, 11)) +>UpperKey : Symbol(UpperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 0, 0)) + +upperKey["FOO"] = 1; // depends on representation +>upperKey : Symbol(upperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 7, 11)) + +upperKey["foo"] = 1; // depends on representation +>upperKey : Symbol(upperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 7, 11)) + +// Index signature whose key is a negation of a string mapping type. +type NotUpperKey = { +>NotUpperKey : Symbol(NotUpperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 9, 20)) + + [idx: string & not Uppercase]: number; +>idx : Symbol(idx, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 13, 5)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +}; + +declare let notUpperKey: NotUpperKey; +>notUpperKey : Symbol(notUpperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 16, 11)) +>NotUpperKey : Symbol(NotUpperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 9, 20)) + +notUpperKey["foo"] = 1; // depends on representation +>notUpperKey : Symbol(notUpperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 16, 11)) + +notUpperKey["FOO"] = 1; // depends on representation +>notUpperKey : Symbol(notUpperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 16, 11)) + +// Mapped type over a string-mapping key type that uses a negated placeholder. +type MappedUpper = { +>MappedUpper : Symbol(MappedUpper, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 18, 23)) + + [k in Uppercase]: number; +>k : Symbol(k, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 22, 5)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) + +}; + +// Generic index signature combination. +type WrapUpperKey = { +>WrapUpperKey : Symbol(WrapUpperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 23, 2)) +>T : Symbol(T, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 26, 18)) + + [idx: Uppercase]: number; +>idx : Symbol(idx, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 27, 5)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 26, 18)) + +}; +type WrapUpperKeyString = WrapUpperKey; +>WrapUpperKeyString : Symbol(WrapUpperKeyString, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 28, 2)) +>WrapUpperKey : Symbol(WrapUpperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 23, 2)) + +type WrapUpperKeyLiteral = WrapUpperKey<"baz">; +>WrapUpperKeyLiteral : Symbol(WrapUpperKeyLiteral, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 29, 47)) +>WrapUpperKey : Symbol(WrapUpperKey, Decl(negatedTypesInStringMappingAndIndexSignatures.ts, 23, 2)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMappingAndIndexSignatures.types b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMappingAndIndexSignatures.types new file mode 100644 index 0000000000000..177fd7c6882b6 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesInStringMappingAndIndexSignatures.types @@ -0,0 +1,78 @@ +//// [tests/cases/conformance/types/negated/negatedTypesInStringMappingAndIndexSignatures.ts] //// + +=== negatedTypesInStringMappingAndIndexSignatures.ts === +// Combination: negated types with BOTH string mapping types and index signatures. + +// Index signature whose key is a string mapping of a negated type. +type UpperKey = { +>UpperKey : UpperKey + + [idx: Uppercase]: number; +>idx : Uppercase<`${string & not "bar"}`> + +}; + +declare let upperKey: UpperKey; +>upperKey : UpperKey + +upperKey["FOO"] = 1; // depends on representation +>upperKey["FOO"] = 1 : 1 +>upperKey["FOO"] : number +>upperKey : UpperKey +>"FOO" : "FOO" +>1 : 1 + +upperKey["foo"] = 1; // depends on representation +>upperKey["foo"] = 1 : 1 +>upperKey["foo"] : any +>upperKey : UpperKey +>"foo" : "foo" +>1 : 1 + +// Index signature whose key is a negation of a string mapping type. +type NotUpperKey = { +>NotUpperKey : NotUpperKey + + [idx: string & not Uppercase]: number; +>idx : string & not Uppercase + +}; + +declare let notUpperKey: NotUpperKey; +>notUpperKey : NotUpperKey + +notUpperKey["foo"] = 1; // depends on representation +>notUpperKey["foo"] = 1 : 1 +>notUpperKey["foo"] : number +>notUpperKey : NotUpperKey +>"foo" : "foo" +>1 : 1 + +notUpperKey["FOO"] = 1; // depends on representation +>notUpperKey["FOO"] = 1 : 1 +>notUpperKey["FOO"] : any +>notUpperKey : NotUpperKey +>"FOO" : "FOO" +>1 : 1 + +// Mapped type over a string-mapping key type that uses a negated placeholder. +type MappedUpper = { +>MappedUpper : MappedUpper + + [k in Uppercase]: number; +}; + +// Generic index signature combination. +type WrapUpperKey = { +>WrapUpperKey : WrapUpperKey + + [idx: Uppercase]: number; +>idx : Uppercase + +}; +type WrapUpperKeyString = WrapUpperKey; +>WrapUpperKeyString : WrapUpperKeyString + +type WrapUpperKeyLiteral = WrapUpperKey<"baz">; +>WrapUpperKeyLiteral : WrapUpperKeyLiteral + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesNormalizationIdentities.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesNormalizationIdentities.errors.txt new file mode 100644 index 0000000000000..1b78c0aecc1bb --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesNormalizationIdentities.errors.txt @@ -0,0 +1,49 @@ +negatedTypesNormalizationIdentities.ts(35,1): error TS2322: Type 'string' is not assignable to type 'never'. +negatedTypesNormalizationIdentities.ts(39,1): error TS2322: Type 'number' is not assignable to type 'string'. + + +==== negatedTypesNormalizationIdentities.ts (2 errors) ==== + // Normalization / identity rules for the `not` type operator. + + // not any => any + type NotAny = not any; + + // not unknown => never + type NotUnknown = not unknown; + + // not never => unknown + type NotNever = not never; + + // Negated nullish / void. + type NotVoid = not void; + type NotNull = not null; + type NotUndefined = not undefined; + + // Double negation collapses: not not T => T. + type DoubleNegString = not not string; + type DoubleNegLiteral = not not "a"; + type TripleNegString = not not not string; // => not string + + // Double negation on a generic type parameter. + type DoubleNeg = not not T; + type DoubleNegApplied = DoubleNeg; + + // Assignability probes confirming the identities. + declare let notNever: NotNever; // unknown + declare let anyVal: any; + declare let str: string; + + notNever = str; // ok (unknown accepts anything) + anyVal = notNever; // ok + + declare let notUnknown: NotUnknown; // never + notUnknown = str; // error (nothing is assignable to never) + ~~~~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'never'. + + declare let dnStr: DoubleNegString; // string + dnStr = "hello"; // ok + dnStr = 0; // error + ~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesNormalizationIdentities.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesNormalizationIdentities.symbols new file mode 100644 index 0000000000000..9a8ae8288f945 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesNormalizationIdentities.symbols @@ -0,0 +1,84 @@ +//// [tests/cases/conformance/types/negated/negatedTypesNormalizationIdentities.ts] //// + +=== negatedTypesNormalizationIdentities.ts === +// Normalization / identity rules for the `not` type operator. + +// not any => any +type NotAny = not any; +>NotAny : Symbol(NotAny, Decl(negatedTypesNormalizationIdentities.ts, 0, 0)) + +// not unknown => never +type NotUnknown = not unknown; +>NotUnknown : Symbol(NotUnknown, Decl(negatedTypesNormalizationIdentities.ts, 3, 22)) + +// not never => unknown +type NotNever = not never; +>NotNever : Symbol(NotNever, Decl(negatedTypesNormalizationIdentities.ts, 6, 30)) + +// Negated nullish / void. +type NotVoid = not void; +>NotVoid : Symbol(NotVoid, Decl(negatedTypesNormalizationIdentities.ts, 9, 26)) + +type NotNull = not null; +>NotNull : Symbol(NotNull, Decl(negatedTypesNormalizationIdentities.ts, 12, 24)) + +type NotUndefined = not undefined; +>NotUndefined : Symbol(NotUndefined, Decl(negatedTypesNormalizationIdentities.ts, 13, 24)) + +// Double negation collapses: not not T => T. +type DoubleNegString = not not string; +>DoubleNegString : Symbol(DoubleNegString, Decl(negatedTypesNormalizationIdentities.ts, 14, 34)) + +type DoubleNegLiteral = not not "a"; +>DoubleNegLiteral : Symbol(DoubleNegLiteral, Decl(negatedTypesNormalizationIdentities.ts, 17, 38)) + +type TripleNegString = not not not string; // => not string +>TripleNegString : Symbol(TripleNegString, Decl(negatedTypesNormalizationIdentities.ts, 18, 36)) + +// Double negation on a generic type parameter. +type DoubleNeg = not not T; +>DoubleNeg : Symbol(DoubleNeg, Decl(negatedTypesNormalizationIdentities.ts, 19, 42)) +>T : Symbol(T, Decl(negatedTypesNormalizationIdentities.ts, 22, 15)) +>T : Symbol(T, Decl(negatedTypesNormalizationIdentities.ts, 22, 15)) + +type DoubleNegApplied = DoubleNeg; +>DoubleNegApplied : Symbol(DoubleNegApplied, Decl(negatedTypesNormalizationIdentities.ts, 22, 30)) +>DoubleNeg : Symbol(DoubleNeg, Decl(negatedTypesNormalizationIdentities.ts, 19, 42)) + +// Assignability probes confirming the identities. +declare let notNever: NotNever; // unknown +>notNever : Symbol(notNever, Decl(negatedTypesNormalizationIdentities.ts, 26, 11)) +>NotNever : Symbol(NotNever, Decl(negatedTypesNormalizationIdentities.ts, 6, 30)) + +declare let anyVal: any; +>anyVal : Symbol(anyVal, Decl(negatedTypesNormalizationIdentities.ts, 27, 11)) + +declare let str: string; +>str : Symbol(str, Decl(negatedTypesNormalizationIdentities.ts, 28, 11)) + +notNever = str; // ok (unknown accepts anything) +>notNever : Symbol(notNever, Decl(negatedTypesNormalizationIdentities.ts, 26, 11)) +>str : Symbol(str, Decl(negatedTypesNormalizationIdentities.ts, 28, 11)) + +anyVal = notNever; // ok +>anyVal : Symbol(anyVal, Decl(negatedTypesNormalizationIdentities.ts, 27, 11)) +>notNever : Symbol(notNever, Decl(negatedTypesNormalizationIdentities.ts, 26, 11)) + +declare let notUnknown: NotUnknown; // never +>notUnknown : Symbol(notUnknown, Decl(negatedTypesNormalizationIdentities.ts, 33, 11)) +>NotUnknown : Symbol(NotUnknown, Decl(negatedTypesNormalizationIdentities.ts, 3, 22)) + +notUnknown = str; // error (nothing is assignable to never) +>notUnknown : Symbol(notUnknown, Decl(negatedTypesNormalizationIdentities.ts, 33, 11)) +>str : Symbol(str, Decl(negatedTypesNormalizationIdentities.ts, 28, 11)) + +declare let dnStr: DoubleNegString; // string +>dnStr : Symbol(dnStr, Decl(negatedTypesNormalizationIdentities.ts, 36, 11)) +>DoubleNegString : Symbol(DoubleNegString, Decl(negatedTypesNormalizationIdentities.ts, 14, 34)) + +dnStr = "hello"; // ok +>dnStr : Symbol(dnStr, Decl(negatedTypesNormalizationIdentities.ts, 36, 11)) + +dnStr = 0; // error +>dnStr : Symbol(dnStr, Decl(negatedTypesNormalizationIdentities.ts, 36, 11)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesNormalizationIdentities.types b/tsc/testdata/baselines/reference/conformance/negatedTypesNormalizationIdentities.types new file mode 100644 index 0000000000000..c302cf52ff099 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesNormalizationIdentities.types @@ -0,0 +1,85 @@ +//// [tests/cases/conformance/types/negated/negatedTypesNormalizationIdentities.ts] //// + +=== negatedTypesNormalizationIdentities.ts === +// Normalization / identity rules for the `not` type operator. + +// not any => any +type NotAny = not any; +>NotAny : any + +// not unknown => never +type NotUnknown = not unknown; +>NotUnknown : never + +// not never => unknown +type NotNever = not never; +>NotNever : unknown + +// Negated nullish / void. +type NotVoid = not void; +>NotVoid : not void + +type NotNull = not null; +>NotNull : not null + +type NotUndefined = not undefined; +>NotUndefined : not undefined + +// Double negation collapses: not not T => T. +type DoubleNegString = not not string; +>DoubleNegString : string + +type DoubleNegLiteral = not not "a"; +>DoubleNegLiteral : "a" + +type TripleNegString = not not not string; // => not string +>TripleNegString : not string + +// Double negation on a generic type parameter. +type DoubleNeg = not not T; +>DoubleNeg : T + +type DoubleNegApplied = DoubleNeg; +>DoubleNegApplied : number + +// Assignability probes confirming the identities. +declare let notNever: NotNever; // unknown +>notNever : unknown + +declare let anyVal: any; +>anyVal : any + +declare let str: string; +>str : string + +notNever = str; // ok (unknown accepts anything) +>notNever = str : string +>notNever : unknown +>str : string + +anyVal = notNever; // ok +>anyVal = notNever : unknown +>anyVal : any +>notNever : unknown + +declare let notUnknown: NotUnknown; // never +>notUnknown : never + +notUnknown = str; // error (nothing is assignable to never) +>notUnknown = str : string +>notUnknown : never +>str : string + +declare let dnStr: DoubleNegString; // string +>dnStr : string + +dnStr = "hello"; // ok +>dnStr = "hello" : "hello" +>dnStr : string +>"hello" : "hello" + +dnStr = 0; // error +>dnStr = 0 : 0 +>dnStr : string +>0 : 0 + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesSatisfiesAndArrays.errors.txt b/tsc/testdata/baselines/reference/conformance/negatedTypesSatisfiesAndArrays.errors.txt new file mode 100644 index 0000000000000..4b8465686efef --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesSatisfiesAndArrays.errors.txt @@ -0,0 +1,56 @@ +negatedTypesSatisfiesAndArrays.ts(8,16): error TS1360: Type 'string' does not satisfy the expected type 'not string'. +negatedTypesSatisfiesAndArrays.ts(11,23): error TS1360: Type 'string' does not satisfy the expected type 'not "reserved"'. +negatedTypesSatisfiesAndArrays.ts(18,8): error TS2322: Type 'string' is not assignable to type 'not string'. +negatedTypesSatisfiesAndArrays.ts(19,11): error TS2322: Type 'string' is not assignable to type 'not string'. +negatedTypesSatisfiesAndArrays.ts(25,9): error TS2322: Type 'string' is not assignable to type 'not string'. +negatedTypesSatisfiesAndArrays.ts(34,8): error TS2345: Argument of type 'string' is not assignable to parameter of type 'not string'. + + +==== negatedTypesSatisfiesAndArrays.ts (6 errors) ==== + // Negated types with the `satisfies` operator and with array/tuple element types. + + // satisfies against a negated type. + declare const n: number; + const s1 = n satisfies not string; // should be ok (number is not a string) + + declare const str: string; + const s2 = str satisfies not string; // should error (string is a string) + ~~~~~~~~~ +!!! error TS1360: Type 'string' does not satisfy the expected type 'not string'. + + const s3 = 42 satisfies not "reserved"; // ok + const s4 = "reserved" satisfies not "reserved"; // should error + ~~~~~~~~~ +!!! error TS1360: Type 'string' does not satisfy the expected type 'not "reserved"'. + + // Array of a negated element type. + type NotStringArray = (not string)[]; + declare let arr: NotStringArray; + arr = [1, 2, 3]; // ok + arr = [{}, true, 0]; // ok: a fresh `{}` literal is treated as a closed empty object, disjoint from `string` + arr = ["a"]; // should error (element is a string) + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'not string'. + arr = [1, "a"]; // should error (one element is a string) + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'not string'. + + // Tuple with a negated element type. + type Pair = [not string, string]; + declare let pair: Pair; + pair = [1, "ok"]; // ok + pair = ["no", "ok"]; // should error (first element is a string) + ~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'not string'. + + // Readonly array of negated element type, element access. + declare const ra: readonly (not number)[]; + const elem = ra[0]; // element type probe + + // Spread / iteration of a negated element array. + function sum(...args: (not string)[]) {} + sum(1, 2, {}); // ok: a fresh `{}` literal is treated as a closed empty object, disjoint from `string` + sum(1, "x"); // should error + ~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'not string'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesSatisfiesAndArrays.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesSatisfiesAndArrays.symbols new file mode 100644 index 0000000000000..88ce594bcce9e --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesSatisfiesAndArrays.symbols @@ -0,0 +1,79 @@ +//// [tests/cases/conformance/types/negated/negatedTypesSatisfiesAndArrays.ts] //// + +=== negatedTypesSatisfiesAndArrays.ts === +// Negated types with the `satisfies` operator and with array/tuple element types. + +// satisfies against a negated type. +declare const n: number; +>n : Symbol(n, Decl(negatedTypesSatisfiesAndArrays.ts, 3, 13)) + +const s1 = n satisfies not string; // should be ok (number is not a string) +>s1 : Symbol(s1, Decl(negatedTypesSatisfiesAndArrays.ts, 4, 5)) +>n : Symbol(n, Decl(negatedTypesSatisfiesAndArrays.ts, 3, 13)) + +declare const str: string; +>str : Symbol(str, Decl(negatedTypesSatisfiesAndArrays.ts, 6, 13)) + +const s2 = str satisfies not string; // should error (string is a string) +>s2 : Symbol(s2, Decl(negatedTypesSatisfiesAndArrays.ts, 7, 5)) +>str : Symbol(str, Decl(negatedTypesSatisfiesAndArrays.ts, 6, 13)) + +const s3 = 42 satisfies not "reserved"; // ok +>s3 : Symbol(s3, Decl(negatedTypesSatisfiesAndArrays.ts, 9, 5)) + +const s4 = "reserved" satisfies not "reserved"; // should error +>s4 : Symbol(s4, Decl(negatedTypesSatisfiesAndArrays.ts, 10, 5)) + +// Array of a negated element type. +type NotStringArray = (not string)[]; +>NotStringArray : Symbol(NotStringArray, Decl(negatedTypesSatisfiesAndArrays.ts, 10, 47)) + +declare let arr: NotStringArray; +>arr : Symbol(arr, Decl(negatedTypesSatisfiesAndArrays.ts, 14, 11)) +>NotStringArray : Symbol(NotStringArray, Decl(negatedTypesSatisfiesAndArrays.ts, 10, 47)) + +arr = [1, 2, 3]; // ok +>arr : Symbol(arr, Decl(negatedTypesSatisfiesAndArrays.ts, 14, 11)) + +arr = [{}, true, 0]; // ok: a fresh `{}` literal is treated as a closed empty object, disjoint from `string` +>arr : Symbol(arr, Decl(negatedTypesSatisfiesAndArrays.ts, 14, 11)) + +arr = ["a"]; // should error (element is a string) +>arr : Symbol(arr, Decl(negatedTypesSatisfiesAndArrays.ts, 14, 11)) + +arr = [1, "a"]; // should error (one element is a string) +>arr : Symbol(arr, Decl(negatedTypesSatisfiesAndArrays.ts, 14, 11)) + +// Tuple with a negated element type. +type Pair = [not string, string]; +>Pair : Symbol(Pair, Decl(negatedTypesSatisfiesAndArrays.ts, 18, 15)) + +declare let pair: Pair; +>pair : Symbol(pair, Decl(negatedTypesSatisfiesAndArrays.ts, 22, 11)) +>Pair : Symbol(Pair, Decl(negatedTypesSatisfiesAndArrays.ts, 18, 15)) + +pair = [1, "ok"]; // ok +>pair : Symbol(pair, Decl(negatedTypesSatisfiesAndArrays.ts, 22, 11)) + +pair = ["no", "ok"]; // should error (first element is a string) +>pair : Symbol(pair, Decl(negatedTypesSatisfiesAndArrays.ts, 22, 11)) + +// Readonly array of negated element type, element access. +declare const ra: readonly (not number)[]; +>ra : Symbol(ra, Decl(negatedTypesSatisfiesAndArrays.ts, 27, 13)) + +const elem = ra[0]; // element type probe +>elem : Symbol(elem, Decl(negatedTypesSatisfiesAndArrays.ts, 28, 5)) +>ra : Symbol(ra, Decl(negatedTypesSatisfiesAndArrays.ts, 27, 13)) + +// Spread / iteration of a negated element array. +function sum(...args: (not string)[]) {} +>sum : Symbol(sum, Decl(negatedTypesSatisfiesAndArrays.ts, 28, 19)) +>args : Symbol(args, Decl(negatedTypesSatisfiesAndArrays.ts, 31, 13)) + +sum(1, 2, {}); // ok: a fresh `{}` literal is treated as a closed empty object, disjoint from `string` +>sum : Symbol(sum, Decl(negatedTypesSatisfiesAndArrays.ts, 28, 19)) + +sum(1, "x"); // should error +>sum : Symbol(sum, Decl(negatedTypesSatisfiesAndArrays.ts, 28, 19)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesSatisfiesAndArrays.types b/tsc/testdata/baselines/reference/conformance/negatedTypesSatisfiesAndArrays.types new file mode 100644 index 0000000000000..52b03f0554a23 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesSatisfiesAndArrays.types @@ -0,0 +1,117 @@ +//// [tests/cases/conformance/types/negated/negatedTypesSatisfiesAndArrays.ts] //// + +=== negatedTypesSatisfiesAndArrays.ts === +// Negated types with the `satisfies` operator and with array/tuple element types. + +// satisfies against a negated type. +declare const n: number; +>n : number + +const s1 = n satisfies not string; // should be ok (number is not a string) +>s1 : number +>n satisfies not string : number +>n : number + +declare const str: string; +>str : string + +const s2 = str satisfies not string; // should error (string is a string) +>s2 : string +>str satisfies not string : string +>str : string + +const s3 = 42 satisfies not "reserved"; // ok +>s3 : 42 +>42 satisfies not "reserved" : 42 +>42 : 42 + +const s4 = "reserved" satisfies not "reserved"; // should error +>s4 : "reserved" +>"reserved" satisfies not "reserved" : "reserved" +>"reserved" : "reserved" + +// Array of a negated element type. +type NotStringArray = (not string)[]; +>NotStringArray : NotStringArray + +declare let arr: NotStringArray; +>arr : NotStringArray + +arr = [1, 2, 3]; // ok +>arr = [1, 2, 3] : number[] +>arr : NotStringArray +>[1, 2, 3] : number[] +>1 : 1 +>2 : 2 +>3 : 3 + +arr = [{}, true, 0]; // ok: a fresh `{}` literal is treated as a closed empty object, disjoint from `string` +>arr = [{}, true, 0] : (number | boolean | {})[] +>arr : NotStringArray +>[{}, true, 0] : (number | boolean | {})[] +>{} : {} +>true : true +>0 : 0 + +arr = ["a"]; // should error (element is a string) +>arr = ["a"] : string[] +>arr : NotStringArray +>["a"] : string[] +>"a" : "a" + +arr = [1, "a"]; // should error (one element is a string) +>arr = [1, "a"] : (string | number)[] +>arr : NotStringArray +>[1, "a"] : (string | number)[] +>1 : 1 +>"a" : "a" + +// Tuple with a negated element type. +type Pair = [not string, string]; +>Pair : Pair + +declare let pair: Pair; +>pair : Pair + +pair = [1, "ok"]; // ok +>pair = [1, "ok"] : [number, string] +>pair : Pair +>[1, "ok"] : [number, string] +>1 : 1 +>"ok" : "ok" + +pair = ["no", "ok"]; // should error (first element is a string) +>pair = ["no", "ok"] : [string, string] +>pair : Pair +>["no", "ok"] : [string, string] +>"no" : "no" +>"ok" : "ok" + +// Readonly array of negated element type, element access. +declare const ra: readonly (not number)[]; +>ra : readonly (not number)[] + +const elem = ra[0]; // element type probe +>elem : not number +>ra[0] : not number +>ra : readonly (not number)[] +>0 : 0 + +// Spread / iteration of a negated element array. +function sum(...args: (not string)[]) {} +>sum : (...args: (not string)[]) => void +>args : (not string)[] + +sum(1, 2, {}); // ok: a fresh `{}` literal is treated as a closed empty object, disjoint from `string` +>sum(1, 2, {}) : void +>sum : (...args: (not string)[]) => void +>1 : 1 +>2 : 2 +>{} : {} + +sum(1, "x"); // should error +>sum(1, "x") : void +>sum : (...args: (not string)[]) => void +>1 : 1 +>"x" : "x" + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesSimplifyInIntersections.js b/tsc/testdata/baselines/reference/conformance/negatedTypesSimplifyInIntersections.js new file mode 100644 index 0000000000000..7be1cd7305bff --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesSimplifyInIntersections.js @@ -0,0 +1,9 @@ +//// [tests/cases/conformance/types/negated/negatedTypesSimplifyInIntersections.ts] //// + +//// [negatedTypesSimplifyInIntersections.ts] +type A = boolean & not true; // false +type B = "w" & not string; // never + + +//// [negatedTypesSimplifyInIntersections.js] +"use strict"; diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesSimplifyInIntersections.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesSimplifyInIntersections.symbols new file mode 100644 index 0000000000000..4cdfe2f75e8fb --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesSimplifyInIntersections.symbols @@ -0,0 +1,9 @@ +//// [tests/cases/conformance/types/negated/negatedTypesSimplifyInIntersections.ts] //// + +=== negatedTypesSimplifyInIntersections.ts === +type A = boolean & not true; // false +>A : Symbol(A, Decl(negatedTypesSimplifyInIntersections.ts, 0, 0)) + +type B = "w" & not string; // never +>B : Symbol(B, Decl(negatedTypesSimplifyInIntersections.ts, 0, 28)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesSimplifyInIntersections.types b/tsc/testdata/baselines/reference/conformance/negatedTypesSimplifyInIntersections.types new file mode 100644 index 0000000000000..384e173a13b75 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesSimplifyInIntersections.types @@ -0,0 +1,10 @@ +//// [tests/cases/conformance/types/negated/negatedTypesSimplifyInIntersections.ts] //// + +=== negatedTypesSimplifyInIntersections.ts === +type A = boolean & not true; // false +>A : false +>true : true + +type B = "w" & not string; // never +>B : never + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesTruthinessFacts.symbols b/tsc/testdata/baselines/reference/conformance/negatedTypesTruthinessFacts.symbols new file mode 100644 index 0000000000000..0c6056e15b359 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesTruthinessFacts.symbols @@ -0,0 +1,91 @@ +//// [tests/cases/conformance/types/negated/negatedTypesTruthinessFacts.ts] //// + +=== negatedTypesTruthinessFacts.ts === +// Type facts for negated types drive control-flow narrowing. An intersection of negated +// falsy values excludes every falsy value, so a truthiness guard on such a type makes the +// falsy branch unreachable (never). This relies on the per-falsy-value "could be" facts, +// which getIntersectionTypeFacts AND-combines and then uses to clear a spurious Falsy fact. + +// A fully-truthy type: excludes every falsy value ("", 0, 0n, null, undefined, false). +type Truthy = not "" & not 0 & not 0n & not null & not undefined & not false; +>Truthy : Symbol(Truthy, Decl(negatedTypesTruthinessFacts.ts, 0, 0)) + +declare const t: Truthy; +>t : Symbol(t, Decl(negatedTypesTruthinessFacts.ts, 8, 13)) +>Truthy : Symbol(Truthy, Decl(negatedTypesTruthinessFacts.ts, 0, 0)) + +if (t) { +>t : Symbol(t, Decl(negatedTypesTruthinessFacts.ts, 8, 13)) + + t; // Truthy +>t : Symbol(t, Decl(negatedTypesTruthinessFacts.ts, 8, 13)) + +} else { + t; // never +>t : Symbol(t, Decl(negatedTypesTruthinessFacts.ts, 8, 13)) +} + +// `string & not ""` is exactly the non-empty strings: truthy, and the falsy branch is unreachable. +declare const s: string & not ""; +>s : Symbol(s, Decl(negatedTypesTruthinessFacts.ts, 16, 13)) + +if (s) { +>s : Symbol(s, Decl(negatedTypesTruthinessFacts.ts, 16, 13)) + + s; // string & not "" +>s : Symbol(s, Decl(negatedTypesTruthinessFacts.ts, 16, 13)) + +} else { + s; // never +>s : Symbol(s, Decl(negatedTypesTruthinessFacts.ts, 16, 13)) +} + +// `number & not 0` is truthy (only falsy number is 0, ignoring NaN like the checker does). +declare const n: number & not 0; +>n : Symbol(n, Decl(negatedTypesTruthinessFacts.ts, 24, 13)) + +if (n) { +>n : Symbol(n, Decl(negatedTypesTruthinessFacts.ts, 24, 13)) + + n; // number & not 0 +>n : Symbol(n, Decl(negatedTypesTruthinessFacts.ts, 24, 13)) + +} else { + n; // never +>n : Symbol(n, Decl(negatedTypesTruthinessFacts.ts, 24, 13)) +} + +// A single negation still leaves the falsy branch reachable: `not null` can be 0/""/false/undefined. +declare const u: not null; +>u : Symbol(u, Decl(negatedTypesTruthinessFacts.ts, 32, 13)) + +if (u) { +>u : Symbol(u, Decl(negatedTypesTruthinessFacts.ts, 32, 13)) + + u; // not null +>u : Symbol(u, Decl(negatedTypesTruthinessFacts.ts, 32, 13)) + +} else { + u; // not null (still falsy-capable, so not never) +>u : Symbol(u, Decl(negatedTypesTruthinessFacts.ts, 32, 13)) +} + +// Omitting `not 0n` leaves 0n as a reachable falsy value, so the falsy branch is not never. +type AlmostTruthy = not "" & not 0 & not null & not undefined & not false; +>AlmostTruthy : Symbol(AlmostTruthy, Decl(negatedTypesTruthinessFacts.ts, 37, 1)) + +declare const a: AlmostTruthy; +>a : Symbol(a, Decl(negatedTypesTruthinessFacts.ts, 41, 13)) +>AlmostTruthy : Symbol(AlmostTruthy, Decl(negatedTypesTruthinessFacts.ts, 37, 1)) + +if (a) { +>a : Symbol(a, Decl(negatedTypesTruthinessFacts.ts, 41, 13)) + + a; // AlmostTruthy +>a : Symbol(a, Decl(negatedTypesTruthinessFacts.ts, 41, 13)) + +} else { + a; // still falsy-capable via 0n, so not never +>a : Symbol(a, Decl(negatedTypesTruthinessFacts.ts, 41, 13)) +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedTypesTruthinessFacts.types b/tsc/testdata/baselines/reference/conformance/negatedTypesTruthinessFacts.types new file mode 100644 index 0000000000000..a81dd86c89fc0 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedTypesTruthinessFacts.types @@ -0,0 +1,91 @@ +//// [tests/cases/conformance/types/negated/negatedTypesTruthinessFacts.ts] //// + +=== negatedTypesTruthinessFacts.ts === +// Type facts for negated types drive control-flow narrowing. An intersection of negated +// falsy values excludes every falsy value, so a truthiness guard on such a type makes the +// falsy branch unreachable (never). This relies on the per-falsy-value "could be" facts, +// which getIntersectionTypeFacts AND-combines and then uses to clear a spurious Falsy fact. + +// A fully-truthy type: excludes every falsy value ("", 0, 0n, null, undefined, false). +type Truthy = not "" & not 0 & not 0n & not null & not undefined & not false; +>Truthy : Truthy +>false : false + +declare const t: Truthy; +>t : Truthy + +if (t) { +>t : Truthy + + t; // Truthy +>t : Truthy + +} else { + t; // never +>t : never +} + +// `string & not ""` is exactly the non-empty strings: truthy, and the falsy branch is unreachable. +declare const s: string & not ""; +>s : string & not "" + +if (s) { +>s : string & not "" + + s; // string & not "" +>s : string & not "" + +} else { + s; // never +>s : never +} + +// `number & not 0` is truthy (only falsy number is 0, ignoring NaN like the checker does). +declare const n: number & not 0; +>n : number & not 0 + +if (n) { +>n : number & not 0 + + n; // number & not 0 +>n : number & not 0 + +} else { + n; // never +>n : never +} + +// A single negation still leaves the falsy branch reachable: `not null` can be 0/""/false/undefined. +declare const u: not null; +>u : not null + +if (u) { +>u : not null + + u; // not null +>u : not null + +} else { + u; // not null (still falsy-capable, so not never) +>u : not null +} + +// Omitting `not 0n` leaves 0n as a reachable falsy value, so the falsy branch is not never. +type AlmostTruthy = not "" & not 0 & not null & not undefined & not false; +>AlmostTruthy : AlmostTruthy +>false : false + +declare const a: AlmostTruthy; +>a : AlmostTruthy + +if (a) { +>a : AlmostTruthy + + a; // AlmostTruthy +>a : AlmostTruthy + +} else { + a; // still falsy-capable via 0n, so not never +>a : AlmostTruthy +} + diff --git a/tsc/testdata/baselines/reference/conformance/negatedUnionComplementSimplifies.symbols b/tsc/testdata/baselines/reference/conformance/negatedUnionComplementSimplifies.symbols new file mode 100644 index 0000000000000..9c0c088c8f4bf --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedUnionComplementSimplifies.symbols @@ -0,0 +1,84 @@ +//// [tests/cases/conformance/types/negated/negatedUnionComplementSimplifies.ts] //// + +=== negatedUnionComplementSimplifies.ts === +// The union converse of the intersection complement simplification: a type unioned with its +// complement covers every value, so `T | not T` reduces to `unknown`. + +// Basic law of excluded middle. +type A = string | not string; +>A : Symbol(A, Decl(negatedUnionComplementSimplifies.ts, 0, 0)) + +declare const a: A; +>a : Symbol(a, Decl(negatedUnionComplementSimplifies.ts, 5, 13)) +>A : Symbol(A, Decl(negatedUnionComplementSimplifies.ts, 0, 0)) + +a; // unknown +>a : Symbol(a, Decl(negatedUnionComplementSimplifies.ts, 5, 13)) + +// A literal unioned with the negation of its base is also unknown, because the base covers the literal. +type B = string | not "w"; +>B : Symbol(B, Decl(negatedUnionComplementSimplifies.ts, 6, 2)) + +declare const b: B; +>b : Symbol(b, Decl(negatedUnionComplementSimplifies.ts, 10, 13)) +>B : Symbol(B, Decl(negatedUnionComplementSimplifies.ts, 6, 2)) + +b; // unknown +>b : Symbol(b, Decl(negatedUnionComplementSimplifies.ts, 10, 13)) + +// An object type and its complement. +interface Point { +>Point : Symbol(Point, Decl(negatedUnionComplementSimplifies.ts, 11, 2)) + + x: number; +>x : Symbol(Point.x, Decl(negatedUnionComplementSimplifies.ts, 14, 17)) + + y: number; +>y : Symbol(Point.y, Decl(negatedUnionComplementSimplifies.ts, 15, 14)) +} +type C = Point | not Point; +>C : Symbol(C, Decl(negatedUnionComplementSimplifies.ts, 17, 1)) +>Point : Symbol(Point, Decl(negatedUnionComplementSimplifies.ts, 11, 2)) +>Point : Symbol(Point, Decl(negatedUnionComplementSimplifies.ts, 11, 2)) + +declare const c: C; +>c : Symbol(c, Decl(negatedUnionComplementSimplifies.ts, 19, 13)) +>C : Symbol(C, Decl(negatedUnionComplementSimplifies.ts, 17, 1)) + +c; // unknown +>c : Symbol(c, Decl(negatedUnionComplementSimplifies.ts, 19, 13)) + +// Type parameter form. +function f(x: T | not T) { +>f : Symbol(f, Decl(negatedUnionComplementSimplifies.ts, 20, 2)) +>T : Symbol(T, Decl(negatedUnionComplementSimplifies.ts, 23, 11)) +>x : Symbol(x, Decl(negatedUnionComplementSimplifies.ts, 23, 14)) +>T : Symbol(T, Decl(negatedUnionComplementSimplifies.ts, 23, 11)) +>T : Symbol(T, Decl(negatedUnionComplementSimplifies.ts, 23, 11)) + + x; // unknown +>x : Symbol(x, Decl(negatedUnionComplementSimplifies.ts, 23, 14)) +} + +// Not saturated: `"w" | not string` is NOT unknown, because `string` is not a subtype of `"w"`. +type D = "w" | not string; +>D : Symbol(D, Decl(negatedUnionComplementSimplifies.ts, 25, 1)) + +declare const d: D; +>d : Symbol(d, Decl(negatedUnionComplementSimplifies.ts, 29, 13)) +>D : Symbol(D, Decl(negatedUnionComplementSimplifies.ts, 25, 1)) + +d; // "w" | not string +>d : Symbol(d, Decl(negatedUnionComplementSimplifies.ts, 29, 13)) + +// Extra non-negated members still saturate when their union covers the negated base. +type E = "w" | string | not string; +>E : Symbol(E, Decl(negatedUnionComplementSimplifies.ts, 30, 2)) + +declare const e: E; +>e : Symbol(e, Decl(negatedUnionComplementSimplifies.ts, 34, 13)) +>E : Symbol(E, Decl(negatedUnionComplementSimplifies.ts, 30, 2)) + +e; // unknown +>e : Symbol(e, Decl(negatedUnionComplementSimplifies.ts, 34, 13)) + diff --git a/tsc/testdata/baselines/reference/conformance/negatedUnionComplementSimplifies.types b/tsc/testdata/baselines/reference/conformance/negatedUnionComplementSimplifies.types new file mode 100644 index 0000000000000..d9b712549f5a7 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/negatedUnionComplementSimplifies.types @@ -0,0 +1,72 @@ +//// [tests/cases/conformance/types/negated/negatedUnionComplementSimplifies.ts] //// + +=== negatedUnionComplementSimplifies.ts === +// The union converse of the intersection complement simplification: a type unioned with its +// complement covers every value, so `T | not T` reduces to `unknown`. + +// Basic law of excluded middle. +type A = string | not string; +>A : unknown + +declare const a: A; +>a : unknown + +a; // unknown +>a : unknown + +// A literal unioned with the negation of its base is also unknown, because the base covers the literal. +type B = string | not "w"; +>B : unknown + +declare const b: B; +>b : unknown + +b; // unknown +>b : unknown + +// An object type and its complement. +interface Point { + x: number; +>x : number + + y: number; +>y : number +} +type C = Point | not Point; +>C : unknown + +declare const c: C; +>c : unknown + +c; // unknown +>c : unknown + +// Type parameter form. +function f(x: T | not T) { +>f : (x: T | not T) => void +>x : unknown + + x; // unknown +>x : unknown +} + +// Not saturated: `"w" | not string` is NOT unknown, because `string` is not a subtype of `"w"`. +type D = "w" | not string; +>D : D + +declare const d: D; +>d : D + +d; // "w" | not string +>d : D + +// Extra non-negated members still saturate when their union covers the negated base. +type E = "w" | string | not string; +>E : unknown + +declare const e: E; +>e : unknown + +e; // unknown +>e : unknown + diff --git a/tsc/testdata/baselines/reference/conformance/parserRealSource14.types b/tsc/testdata/baselines/reference/conformance/parserRealSource14.types index 5127066179986..a7fde9101cc33 100644 --- a/tsc/testdata/baselines/reference/conformance/parserRealSource14.types +++ b/tsc/testdata/baselines/reference/conformance/parserRealSource14.types @@ -27,9 +27,9 @@ namespace TypeScript { >items[items.length - 1] : any >items : any[] >items.length - 1 : number ->items.length : number +>items.length : number & not 0 >items : any[] ->length : number +>length : number & not 0 >1 : 1 } diff --git a/tsc/testdata/baselines/reference/conformance/parserS7.2_A1.5_T2.types b/tsc/testdata/baselines/reference/conformance/parserS7.2_A1.5_T2.types index 1b339e8766325..a4d31ae4a4c8a 100644 --- a/tsc/testdata/baselines/reference/conformance/parserS7.2_A1.5_T2.types +++ b/tsc/testdata/baselines/reference/conformance/parserS7.2_A1.5_T2.types @@ -46,8 +46,8 @@ if (x !== 1) { >$ERROR : any >'#2:  var x = 1 ; x === 1. Actual: ' + (x) : string >'#2:  var x = 1 ; x === 1. Actual: ' : "#2:  var x = 1 ; x === 1. Actual: " ->(x) : number ->x : number +>(x) : number & not 1 +>x : number & not 1 } diff --git a/tsc/testdata/baselines/reference/conformance/parserS7.3_A1.1_T2.types b/tsc/testdata/baselines/reference/conformance/parserS7.3_A1.1_T2.types index ba93c73c7c10a..ded8704562d67 100644 --- a/tsc/testdata/baselines/reference/conformance/parserS7.3_A1.1_T2.types +++ b/tsc/testdata/baselines/reference/conformance/parserS7.3_A1.1_T2.types @@ -30,8 +30,8 @@ if (x !== 1) { >$ERROR : any >'#1: var\\nx\\n=\\n1\\n; x === 1. Actual: ' + (x) : string >'#1: var\\nx\\n=\\n1\\n; x === 1. Actual: ' : "#1: var\\nx\\n=\\n1\\n; x === 1. Actual: " ->(x) : number ->x : number +>(x) : number & not 1 +>x : number & not 1 } diff --git a/tsc/testdata/baselines/reference/conformance/parserUnicode1.types b/tsc/testdata/baselines/reference/conformance/parserUnicode1.types index aa318212207dc..ccd241dfc438e 100644 --- a/tsc/testdata/baselines/reference/conformance/parserUnicode1.types +++ b/tsc/testdata/baselines/reference/conformance/parserUnicode1.types @@ -16,8 +16,8 @@ try { >$ERROR : any >'#6.1: var \\u0078x = 1; xx === 6. Actual: ' + (xx) : string >'#6.1: var \\u0078x = 1; xx === 6. Actual: ' : "#6.1: var \\u0078x = 1; xx === 6. Actual: " ->(xx) : number ->xx : number +>(xx) : number & not 6 +>xx : number & not 6 } } catch (e) { diff --git a/tsc/testdata/baselines/reference/conformance/parserharness.types b/tsc/testdata/baselines/reference/conformance/parserharness.types index 34c24f4588dfd..a4734d7645998 100644 --- a/tsc/testdata/baselines/reference/conformance/parserharness.types +++ b/tsc/testdata/baselines/reference/conformance/parserharness.types @@ -756,7 +756,7 @@ namespace Harness { >"Expected array to match element only once (instead of " + foundCount + " times)" : string >"Expected array to match element only once (instead of " + foundCount : string >"Expected array to match element only once (instead of " : "Expected array to match element only once (instead of " ->foundCount : number +>foundCount : number & not 1 >" times)" : " times)" } } @@ -2779,7 +2779,7 @@ namespace Harness { >'////[' + p + ']' : string >'////[' + p : string >'////[' : "////[" ->p : string +>p : string & not "0.js" >']' : "]" result.push({ filename: p, file: this.fileCollection[p] }); @@ -4093,9 +4093,9 @@ namespace Harness { } else if (matchingIdentifiers.length > 1) { >matchingIdentifiers.length > 1 : boolean ->matchingIdentifiers.length : number +>matchingIdentifiers.length : number & not 0 >matchingIdentifiers : Type[] ->length : number +>length : number & not 0 >1 : 1 throw new Error("Found multiple matching identifiers for " + target); diff --git a/tsc/testdata/baselines/reference/conformance/returnTagTypeGuard.types b/tsc/testdata/baselines/reference/conformance/returnTagTypeGuard.types index b3aa4278fb80b..1f4b208f8bfde 100644 --- a/tsc/testdata/baselines/reference/conformance/returnTagTypeGuard.types +++ b/tsc/testdata/baselines/reference/conformance/returnTagTypeGuard.types @@ -64,7 +64,7 @@ function f(chunk) { >chunk : Entry >c : number >chunk.d : string ->chunk : Group +>chunk : Group & not Entry >d : string return x diff --git a/tsc/testdata/baselines/reference/conformance/scannerS7.2_A1.5_T2.types b/tsc/testdata/baselines/reference/conformance/scannerS7.2_A1.5_T2.types index 055453746905d..435c4474b98b3 100644 --- a/tsc/testdata/baselines/reference/conformance/scannerS7.2_A1.5_T2.types +++ b/tsc/testdata/baselines/reference/conformance/scannerS7.2_A1.5_T2.types @@ -46,8 +46,8 @@ if (x !== 1) { >$ERROR : any >'#2:  var x = 1 ; x === 1. Actual: ' + (x) : string >'#2:  var x = 1 ; x === 1. Actual: ' : "#2:  var x = 1 ; x === 1. Actual: " ->(x) : number ->x : number +>(x) : number & not 1 +>x : number & not 1 } diff --git a/tsc/testdata/baselines/reference/conformance/scannerS7.3_A1.1_T2.types b/tsc/testdata/baselines/reference/conformance/scannerS7.3_A1.1_T2.types index 3fb7d6c930ab9..5cb673cd8b1b8 100644 --- a/tsc/testdata/baselines/reference/conformance/scannerS7.3_A1.1_T2.types +++ b/tsc/testdata/baselines/reference/conformance/scannerS7.3_A1.1_T2.types @@ -30,8 +30,8 @@ if (x !== 1) { >$ERROR : any >'#1: var\\nx\\n=\\n1\\n; x === 1. Actual: ' + (x) : string >'#1: var\\nx\\n=\\n1\\n; x === 1. Actual: ' : "#1: var\\nx\\n=\\n1\\n; x === 1. Actual: " ->(x) : number ->x : number +>(x) : number & not 1 +>x : number & not 1 } diff --git a/tsc/testdata/baselines/reference/conformance/staticIndexSignature4.types b/tsc/testdata/baselines/reference/conformance/staticIndexSignature4.types index 5e5bd4c487319..25803d8c9cff7 100644 --- a/tsc/testdata/baselines/reference/conformance/staticIndexSignature4.types +++ b/tsc/testdata/baselines/reference/conformance/staticIndexSignature4.types @@ -60,7 +60,7 @@ if (v === 0) { } else if (v === 1) { >v === 1 : boolean ->v : number +>v : number & not 0 >1 : 1 D.a = B.a @@ -83,7 +83,7 @@ if (v === 0) { } else if (v === 2) { >v === 2 : boolean ->v : number +>v : number & not 0 & not 1 >2 : 2 B.a = i.a @@ -124,7 +124,7 @@ if (v === 0) { } else if (v === 3) { >v === 3 : boolean ->v : number +>v : number & not 0 & not 1 & not 2 >3 : 3 i.a = B.a @@ -147,7 +147,7 @@ if (v === 0) { } else if (v === 4) { >v === 4 : boolean ->v : number +>v : number & not 0 & not 1 & not 2 & not 3 >4 : 4 i.a = D.a diff --git a/tsc/testdata/baselines/reference/conformance/stringLiteralCheckedInIf01.types b/tsc/testdata/baselines/reference/conformance/stringLiteralCheckedInIf01.types index 0e9ca2ed78d8f..d93d15b2c0e2d 100644 --- a/tsc/testdata/baselines/reference/conformance/stringLiteralCheckedInIf01.types +++ b/tsc/testdata/baselines/reference/conformance/stringLiteralCheckedInIf01.types @@ -8,7 +8,7 @@ type T = S[] | S; >T : T function f(foo: T) { ->f : (foo: T) => S +>f : (foo: T) => S | (S[] & not "a") >foo : T if (foo === "a") { @@ -21,18 +21,18 @@ function f(foo: T) { } else if (foo === "b") { >foo === "b" : boolean ->foo : "b" | S[] +>foo : "b" | (S[] & not "a") >"b" : "b" return foo; ->foo : "b" +>foo : "b" | (S[] & not "a") } else { return (foo as S[])[0]; >(foo as S[])[0] : S >(foo as S[]) : S[] >foo as S[] : S[] ->foo : S[] +>foo : S[] & not "a" & not "b" >0 : 0 } } diff --git a/tsc/testdata/baselines/reference/conformance/stringLiteralCheckedInIf02.types b/tsc/testdata/baselines/reference/conformance/stringLiteralCheckedInIf02.types index 21cf82b197205..dc25e3c7c22a0 100644 --- a/tsc/testdata/baselines/reference/conformance/stringLiteralCheckedInIf02.types +++ b/tsc/testdata/baselines/reference/conformance/stringLiteralCheckedInIf02.types @@ -17,7 +17,7 @@ function isS(t: T): t is S { >t : T >"a" : "a" >t === "b" : boolean ->t : "b" | S[] +>t : "b" | (S[] & not "a") >"b" : "b" } @@ -36,7 +36,7 @@ function f(foo: T) { else { return foo[0]; >foo[0] : S ->foo : S[] +>foo : S[] & not "a" & not "b" >0 : 0 } } diff --git a/tsc/testdata/baselines/reference/conformance/stringLiteralTypesInUnionTypes02.types b/tsc/testdata/baselines/reference/conformance/stringLiteralTypesInUnionTypes02.types index c8ec0ef98f1f5..0bbd70b5cbbf2 100644 --- a/tsc/testdata/baselines/reference/conformance/stringLiteralTypesInUnionTypes02.types +++ b/tsc/testdata/baselines/reference/conformance/stringLiteralTypesInUnionTypes02.types @@ -23,19 +23,19 @@ if (x === "foo") { } else if (x !== "bar") { >x !== "bar" : boolean ->x : string +>x : string & not "foo" >"bar" : "bar" let b = x || y; >b : string >x || y : string ->x : string +>x : string & not "foo" & not "bar" >y : string } else { let c = x; >c : string ->x : "bar" +>x : string & not "foo" let d = y; >d : string @@ -43,7 +43,7 @@ else { let e: (typeof x) | (typeof y) = c || d; >e : string ->x : "bar" +>x : string & not "foo" >y : string >c || d : string >c : string diff --git a/tsc/testdata/baselines/reference/conformance/stringLiteralTypesOverloads02.types b/tsc/testdata/baselines/reference/conformance/stringLiteralTypesOverloads02.types index 6ac09aefb846b..9084228335e5d 100644 --- a/tsc/testdata/baselines/reference/conformance/stringLiteralTypesOverloads02.types +++ b/tsc/testdata/baselines/reference/conformance/stringLiteralTypesOverloads02.types @@ -43,7 +43,7 @@ function getFalsyPrimitive(x: string): string | number | boolean { } if (x === "number") { >x === "number" : boolean ->x : string +>x : string & not "string" >"number" : "number" return 0; @@ -51,7 +51,7 @@ function getFalsyPrimitive(x: string): string | number | boolean { } if (x === "boolean") { >x === "boolean" : boolean ->x : string +>x : string & not "string" & not "number" >"boolean" : "boolean" return false; diff --git a/tsc/testdata/baselines/reference/conformance/symbolType17.types b/tsc/testdata/baselines/reference/conformance/symbolType17.types index 7f599ae73db40..5518f2831080b 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolType17.types +++ b/tsc/testdata/baselines/reference/conformance/symbolType17.types @@ -21,5 +21,5 @@ if (typeof x === "symbol") { } else { x; ->x : Foo +>x : Foo & not symbol } diff --git a/tsc/testdata/baselines/reference/conformance/typeGuardFunction.types b/tsc/testdata/baselines/reference/conformance/typeGuardFunction.types index 6a1ccbc3c8d40..f90df13411184 100644 --- a/tsc/testdata/baselines/reference/conformance/typeGuardFunction.types +++ b/tsc/testdata/baselines/reference/conformance/typeGuardFunction.types @@ -185,9 +185,9 @@ let union2: C | B; let union3: boolean | B = isA(union2) || union2; >union3 : boolean | B ->isA(union2) || union2 : true | B +>isA(union2) || union2 : true | (B & not A) >isA(union2) : boolean >isA : (p1: any) => p1 is A >union2 : B | C ->union2 : B +>union2 : B & not A diff --git a/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThis.symbols b/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThis.symbols index 99c0867473c5e..7321980a2f02d 100644 --- a/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThis.symbols +++ b/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThis.symbols @@ -251,9 +251,9 @@ else if (crate.isSupplies()) { crate.contents.spoiled = true; >crate.contents.spoiled : Symbol(Supplies.spoiled, Decl(typeGuardFunctionOfFormThis.ts, 83, 20)) ->crate.contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20)) +>crate.contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20), Decl(typeGuardFunctionOfFormThis.ts, 91, 20)) >crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3)) ->contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20)) +>contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20), Decl(typeGuardFunctionOfFormThis.ts, 91, 20)) >spoiled : Symbol(Supplies.spoiled, Decl(typeGuardFunctionOfFormThis.ts, 83, 20)) } diff --git a/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThis.types b/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThis.types index 41b1159af276b..94ca01912c390 100644 --- a/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThis.types +++ b/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThis.types @@ -58,13 +58,13 @@ if (a.isLeader()) { else if (a.isFollower()) { >a.isFollower() : boolean >a.isFollower : () => this is FollowerGuard ->a : RoyalGuard +>a : RoyalGuard & not LeadGuard >isFollower : () => this is FollowerGuard a.follow(); >a.follow() : void >a.follow : () => void ->a : FollowerGuard +>a : RoyalGuard & not LeadGuard & FollowerGuard >follow : () => void } @@ -88,13 +88,13 @@ if (b.isLeader()) { else if (b.isFollower()) { >b.isFollower() : boolean >b.isFollower : () => this is FollowerGuard ->b : GuardInterface +>b : GuardInterface & not LeadGuard >isFollower : () => this is FollowerGuard b.follow(); >b.follow() : void >b.follow : () => void ->b : FollowerGuard +>b : GuardInterface & not LeadGuard & FollowerGuard >follow : () => void } @@ -132,9 +132,9 @@ if (holder2.a.isLeader()) { } else { holder2.a; ->holder2.a : RoyalGuard +>holder2.a : RoyalGuard & not LeadGuard >holder2 : { a: RoyalGuard; } ->a : RoyalGuard +>a : RoyalGuard & not LeadGuard } class ArrowGuard { @@ -196,13 +196,13 @@ if (guard.isElite()) { else if (guard.isMedic()) { >guard.isMedic() : boolean >guard.isMedic : () => this is ArrowMedic ->guard : ArrowGuard +>guard : ArrowGuard & not ArrowElite >isMedic : () => this is ArrowMedic guard.heal(); >guard.heal() : void >guard.heal : () => void ->guard : ArrowMedic +>guard : ArrowGuard & not ArrowElite & ArrowMedic >heal : () => void } @@ -251,14 +251,14 @@ if (crate.isSundries()) { else if (crate.isSupplies()) { >crate.isSupplies() : boolean >crate.isSupplies : () => this is Crate ->crate : Crate<{}> +>crate : Crate<{}> & not Crate >isSupplies : () => this is Crate crate.contents.spoiled = true; >crate.contents.spoiled = true : true >crate.contents.spoiled : boolean >crate.contents : Supplies ->crate : Crate +>crate : Crate<{}> & not Crate & Crate >contents : Supplies >spoiled : boolean >true : true diff --git a/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThisErrors.types b/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThisErrors.types index 83f6d8adbbc0d..1e2106038137d 100644 --- a/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThisErrors.types +++ b/tsc/testdata/baselines/reference/conformance/typeGuardFunctionOfFormThisErrors.types @@ -133,7 +133,7 @@ else { >c : number | number[] holder; ->holder : { invalidGuard: (c: any) => this is number; } +>holder : { invalidGuard: (c: any) => this is number; } & not number } let detached = a.isFollower; diff --git a/tsc/testdata/baselines/reference/conformance/typeGuardIntersectionTypes.types b/tsc/testdata/baselines/reference/conformance/typeGuardIntersectionTypes.types index 2cd1a1602b181..2fe798416cdd7 100644 --- a/tsc/testdata/baselines/reference/conformance/typeGuardIntersectionTypes.types +++ b/tsc/testdata/baselines/reference/conformance/typeGuardIntersectionTypes.types @@ -40,13 +40,13 @@ function f1(obj: Object) { >obj : Object >isY(obj) : boolean >isY : (obj: any) => obj is Y ->obj : Object +>obj : Object & not X >isZ(obj) : boolean >isZ : (obj: any) => obj is Z ->obj : Object +>obj : Object & not X & not Y obj; ->obj : X | Y | Z +>obj : X | (Object & not X & Y) | (Object & not X & not Y & Z) } if (isX(obj) && isY(obj) && isZ(obj)) { >isX(obj) && isY(obj) && isZ(obj) : boolean @@ -182,9 +182,9 @@ function identifyBeast(beast: Beast) { } else if (beast.legs === 2) { >beast.legs === 2 : boolean ->beast.legs : number +>beast.legs : number & not 4 >beast : Legged & Winged ->legs : number +>legs : number & not 4 >2 : 2 log(`bird - 2 legs, wings`); @@ -197,9 +197,9 @@ function identifyBeast(beast: Beast) { >log(`unknown - ${beast.legs} legs, wings`) : void >log : (s: string) => void >`unknown - ${beast.legs} legs, wings` : string ->beast.legs : number +>beast.legs : number & not 4 & not 2 >beast : Legged & Winged ->legs : number +>legs : number & not 4 & not 2 } } @@ -210,7 +210,7 @@ function identifyBeast(beast: Beast) { >log : (s: string) => void >`manbearpig - ${beast.legs} legs, no wings` : string >beast.legs : number ->beast : Legged +>beast : Legged & not Winged >legs : number } } @@ -220,7 +220,7 @@ function identifyBeast(beast: Beast) { if (hasWings(beast)) { >hasWings(beast) : boolean >hasWings : (x: Beast) => x is Winged ->beast : Beast +>beast : Beast & not Legged log(`quetzalcoatl - no legs, wings`) >log(`quetzalcoatl - no legs, wings`) : void @@ -254,7 +254,7 @@ function beastFoo(beast: Object) { } else { beast; ->beast : Object +>beast : (Object & not Winged) | (Winged & not Legged) } if (hasLegs(beast) && hasWings(beast)) { diff --git a/tsc/testdata/baselines/reference/conformance/typeGuardOfFormExpr1AndExpr2.types b/tsc/testdata/baselines/reference/conformance/typeGuardOfFormExpr1AndExpr2.types index 6799c40860c70..ae86c2b87d644 100644 --- a/tsc/testdata/baselines/reference/conformance/typeGuardOfFormExpr1AndExpr2.types +++ b/tsc/testdata/baselines/reference/conformance/typeGuardOfFormExpr1AndExpr2.types @@ -70,17 +70,17 @@ if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "numbe >"string" : "string" >typeof strOrNumOrBoolOrC !== "number" : boolean >typeof strOrNumOrBoolOrC : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->strOrNumOrBoolOrC : number | boolean | C +>strOrNumOrBoolOrC : number | boolean | (C & not string) >"number" : "number" >typeof strOrNumOrBoolOrC !== "boolean" : boolean >typeof strOrNumOrBoolOrC : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->strOrNumOrBoolOrC : boolean | C +>strOrNumOrBoolOrC : boolean | (C & not string & not number) >"boolean" : "boolean" c = strOrNumOrBoolOrC; // C ->c = strOrNumOrBoolOrC : C +>c = strOrNumOrBoolOrC : C & not string & not number & not false & not true >c : C ->strOrNumOrBoolOrC : C +>strOrNumOrBoolOrC : C & not string & not number & not false & not true } else { strOrNumOrBool = strOrNumOrBoolOrC; // string | number | boolean @@ -94,11 +94,11 @@ if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "numbe >typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" : boolean >typeof strOrNumOrBoolOrC !== "string" : boolean >typeof strOrNumOrBoolOrC : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->strOrNumOrBoolOrC : string | number | boolean | C +>strOrNumOrBoolOrC : string | number | boolean | (C & not string & not number & not false & not true) >"string" : "string" >typeof strOrNumOrBoolOrC !== "number" : boolean >typeof strOrNumOrBoolOrC : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->strOrNumOrBoolOrC : number | boolean | C +>strOrNumOrBoolOrC : number | boolean | (C & not string & not number & not false & not true) >"number" : "number" >typeof strOrNumOrBool === "boolean" : boolean >typeof strOrNumOrBool : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" @@ -106,9 +106,9 @@ if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "numbe >"boolean" : "boolean" cOrBool = strOrNumOrBoolOrC; // C | boolean ->cOrBool = strOrNumOrBoolOrC : boolean | C +>cOrBool = strOrNumOrBoolOrC : boolean | (C & not string & not number & not false & not true) >cOrBool : boolean | C ->strOrNumOrBoolOrC : boolean | C +>strOrNumOrBoolOrC : boolean | (C & not string & not number & not false & not true) bool = strOrNumOrBool; // boolean >bool = strOrNumOrBool : boolean @@ -118,7 +118,7 @@ if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "numbe else { var r1: string | number | boolean | C = strOrNumOrBoolOrC; // string | number | boolean | C >r1 : string | number | boolean | C ->strOrNumOrBoolOrC : string | number | boolean | C +>strOrNumOrBoolOrC : string | number | boolean | (C & not string & not number & not false & not true) var r2: string | number | boolean = strOrNumOrBool; >r2 : string | number | boolean diff --git a/tsc/testdata/baselines/reference/conformance/typeGuardOfFormExpr1OrExpr2.types b/tsc/testdata/baselines/reference/conformance/typeGuardOfFormExpr1OrExpr2.types index fd4f477e0014d..993ae90f5410b 100644 --- a/tsc/testdata/baselines/reference/conformance/typeGuardOfFormExpr1OrExpr2.types +++ b/tsc/testdata/baselines/reference/conformance/typeGuardOfFormExpr1OrExpr2.types @@ -70,11 +70,11 @@ if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "numbe >"string" : "string" >typeof strOrNumOrBoolOrC === "number" : boolean >typeof strOrNumOrBoolOrC : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->strOrNumOrBoolOrC : number | boolean | C +>strOrNumOrBoolOrC : number | boolean | (C & not string) >"number" : "number" >typeof strOrNumOrBoolOrC === "boolean" : boolean >typeof strOrNumOrBoolOrC : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->strOrNumOrBoolOrC : boolean | C +>strOrNumOrBoolOrC : boolean | (C & not string & not number) >"boolean" : "boolean" strOrNumOrBool = strOrNumOrBoolOrC; // string | number | boolean @@ -84,9 +84,9 @@ if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "numbe } else { c = strOrNumOrBoolOrC; // C ->c = strOrNumOrBoolOrC : C +>c = strOrNumOrBoolOrC : C & not string & not number & not false & not true >c : C ->strOrNumOrBoolOrC : C +>strOrNumOrBoolOrC : C & not string & not number & not false & not true } // (typeguard1 || typeguard2 || typeguard11(onAnotherType)) if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBool !== "boolean") { @@ -94,11 +94,11 @@ if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "numbe >typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" : boolean >typeof strOrNumOrBoolOrC === "string" : boolean >typeof strOrNumOrBoolOrC : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->strOrNumOrBoolOrC : string | number | boolean | C +>strOrNumOrBoolOrC : string | number | boolean | (C & not string & not number & not false & not true) >"string" : "string" >typeof strOrNumOrBoolOrC === "number" : boolean >typeof strOrNumOrBoolOrC : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->strOrNumOrBoolOrC : number | boolean | C +>strOrNumOrBoolOrC : number | boolean | (C & not string & not number & not false & not true) >"number" : "number" >typeof strOrNumOrBool !== "boolean" : boolean >typeof strOrNumOrBool : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" @@ -107,7 +107,7 @@ if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "numbe var r1: string | number | boolean | C = strOrNumOrBoolOrC; // string | number | boolean | C >r1 : string | number | boolean | C ->strOrNumOrBoolOrC : string | number | boolean | C +>strOrNumOrBoolOrC : string | number | boolean | (C & not string & not number & not false & not true) var r2: string | number | boolean = strOrNumOrBool; >r2 : string | number | boolean @@ -115,9 +115,9 @@ if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "numbe } else { cOrBool = strOrNumOrBoolOrC; // C | boolean ->cOrBool = strOrNumOrBoolOrC : boolean | C +>cOrBool = strOrNumOrBoolOrC : boolean | (C & not string & not number & not false & not true) >cOrBool : boolean | C ->strOrNumOrBoolOrC : boolean | C +>strOrNumOrBoolOrC : boolean | (C & not string & not number & not false & not true) bool = strOrNumOrBool; // boolean >bool = strOrNumOrBool : boolean diff --git a/tsc/testdata/baselines/reference/conformance/typeGuardsOnClassProperty.types b/tsc/testdata/baselines/reference/conformance/typeGuardsOnClassProperty.types index 15a7b0c0baedc..312d1490a5c87 100644 --- a/tsc/testdata/baselines/reference/conformance/typeGuardsOnClassProperty.types +++ b/tsc/testdata/baselines/reference/conformance/typeGuardsOnClassProperty.types @@ -30,7 +30,7 @@ class D { >data : string >data.join(" ") : string >data.join : (separator?: string) => string ->data : string[] +>data : string[] & not string >join : (separator?: string) => string >" " : " " } @@ -51,9 +51,9 @@ class D { >data : string >this.data.join(" ") : string >this.data.join : (separator?: string) => string ->this.data : string[] +>this.data : string[] & not string >this : this ->data : string[] +>data : string[] & not string >join : (separator?: string) => string >" " : " " } diff --git a/tsc/testdata/baselines/reference/conformance/unionAndIntersectionInference1.types b/tsc/testdata/baselines/reference/conformance/unionAndIntersectionInference1.types index 04e31e1c8ecf2..14243a6df9868 100644 --- a/tsc/testdata/baselines/reference/conformance/unionAndIntersectionInference1.types +++ b/tsc/testdata/baselines/reference/conformance/unionAndIntersectionInference1.types @@ -97,7 +97,7 @@ function foo1(value: void|a): void { } else { value; // value is a ->value : a +>value : a & not void } } @@ -115,7 +115,7 @@ function baz1(value: void|a): void { } else { value; // value is void ->value : void +>value : void & not a } } diff --git a/tsc/testdata/baselines/reference/conformance/unknownControlFlow.types b/tsc/testdata/baselines/reference/conformance/unknownControlFlow.types index 888876188e366..6022e821ddaf5 100644 --- a/tsc/testdata/baselines/reference/conformance/unknownControlFlow.types +++ b/tsc/testdata/baselines/reference/conformance/unknownControlFlow.types @@ -663,14 +663,14 @@ function deepEquals(a: T, b: T): boolean { >Object.keys : { (o: object): string[]; (o: {}): string[]; } >Object : ObjectConstructor >keys : { (o: object): string[]; (o: {}): string[]; } ->a : T & object +>a : T & object & not any[] >length : number >Object.keys(b).length : number >Object.keys(b) : string[] >Object.keys : { (o: object): string[]; (o: {}): string[]; } >Object : ObjectConstructor >keys : { (o: object): string[]; (o: {}): string[]; } ->b : T & object +>b : T & object & not any[] >length : number return false; @@ -795,7 +795,7 @@ function fx0(value: T & ({} | null)) { } else { value; // T & ({} | null) ->value : T & ({} | null) +>value : (T & ({} | null)) & not 42 } } @@ -813,7 +813,7 @@ function fx1(value: T & ({} | null)) { } else { value; // T & ({} | null) ->value : T & ({} | null) +>value : (T & ({} | null)) & not 42 } } @@ -831,7 +831,7 @@ function fx2(value: T & ({} | null)) { } else { value; // T & ({} | null) ->value : T +>value : T & not 42 } } @@ -849,7 +849,7 @@ function fx3(value: T & ({} | null)) { } else { value; // T & ({} | null) ->value : T & {} +>value : T & {} & not 42 } } @@ -867,7 +867,7 @@ function fx4(value: T & ({} | null)) { } else { value; // T & ({} | null) ->value : T +>value : T & not 42 } } @@ -885,7 +885,7 @@ function fx5(value: T & ({} | null)) { } else { value; // T & ({} | null) ->value : T & ({} | null) +>value : (T & ({} | null)) & not 42 } } @@ -970,7 +970,7 @@ function doSomething1(value: T): T { >'Meaning of life value' : "Meaning of life value" } return value; ->value : T & ({} | null) +>value : (T & ({} | null)) & not 42 } function doSomething2(value: unknown): void { @@ -1082,12 +1082,12 @@ function fx20(value: Either) { } else if (value === 'right') { >value === 'right' : boolean ->value : Right +>value : "right" & { right: 'right'; } >'right' : "right" const bar: 'right' = value; >bar : "right" ->value : Right +>value : "right" & { right: 'right'; } } else { assertNever(value); diff --git a/tsc/testdata/baselines/reference/conformance/unknownType1.types b/tsc/testdata/baselines/reference/conformance/unknownType1.types index 5c79a18e45c02..301347352af12 100644 --- a/tsc/testdata/baselines/reference/conformance/unknownType1.types +++ b/tsc/testdata/baselines/reference/conformance/unknownType1.types @@ -202,7 +202,7 @@ function f20(x: unknown) { >"string" : "string" >typeof x === "number" : boolean >typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined" ->x : unknown +>x : not string >"number" : "number" x; // string | number diff --git a/tsc/testdata/baselines/reference/conformance/unknownType2.errors.txt b/tsc/testdata/baselines/reference/conformance/unknownType2.errors.txt index c5539f06696e4..a1cd193cede34 100644 --- a/tsc/testdata/baselines/reference/conformance/unknownType2.errors.txt +++ b/tsc/testdata/baselines/reference/conformance/unknownType2.errors.txt @@ -1,8 +1,10 @@ +unknownType2.ts(33,21): error TS2344: Type 'false' does not satisfy the constraint 'true'. +unknownType2.ts(37,21): error TS2344: Type 'false' does not satisfy the constraint 'true'. unknownType2.ts(216,13): error TS2322: Type '"maybe" | "no" | "yes"' is not assignable to type 'SomeResponse'. Type '"maybe"' is not assignable to type 'SomeResponse'. -==== unknownType2.ts (1 errors) ==== +==== unknownType2.ts (3 errors) ==== type isUnknown = unknown extends T ? true : false; type isTrue = T; @@ -36,10 +38,14 @@ unknownType2.ts(216,13): error TS2322: Type '"maybe" | "no" | "yes"' is not assi if (!(u === 42)) { type A = isTrue> + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'false' does not satisfy the constraint 'true'. } if (u !== 42) { type B = isTrue> + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'false' does not satisfy the constraint 'true'. } if (u == 42) { diff --git a/tsc/testdata/baselines/reference/conformance/unknownType2.types b/tsc/testdata/baselines/reference/conformance/unknownType2.types index 42e661f5fecc8..d6778edeae97a 100644 --- a/tsc/testdata/baselines/reference/conformance/unknownType2.types +++ b/tsc/testdata/baselines/reference/conformance/unknownType2.types @@ -25,7 +25,7 @@ let validate: (x: unknown) => SomeResponse = x => (x === 'yes' || x === 'no') ? >x : unknown >'yes' : "yes" >x === 'no' : boolean ->x : unknown +>x : not "yes" >'no' : "no" >x : "no" | "yes" >'idk' : "idk" @@ -60,7 +60,7 @@ if (u === true || u === false) { >u : unknown >true : true >u === false : boolean ->u : unknown +>u : not true >false : false const someBool: boolean = u; @@ -106,8 +106,8 @@ if (!(u === 42)) { >42 : 42 type A = isTrue> ->A : true ->u : unknown +>A : false +>u : not 42 } if (u !== 42) { @@ -116,8 +116,8 @@ if (u !== 42) { >42 : 42 type B = isTrue> ->B : true ->u : unknown +>B : false +>u : not 42 } if (u == 42) { @@ -687,12 +687,12 @@ function notNotEquals(u: unknown) { >NumberEnum : typeof NumberEnum >A : NumberEnum.A >u !== NumberEnum.B : boolean ->u : unknown +>u : not NumberEnum.A >NumberEnum.B : NumberEnum.B >NumberEnum : typeof NumberEnum >B : NumberEnum.B >u !== StringEnum.A : boolean ->u : unknown +>u : not NumberEnum.A & not NumberEnum.B >StringEnum.A : StringEnum.A >StringEnum : typeof StringEnum >A : StringEnum.A @@ -718,12 +718,12 @@ function notNotEquals(u: unknown) { >NumberEnum : typeof NumberEnum >A : NumberEnum.A >u === NumberEnum.B : boolean ->u : unknown +>u : not NumberEnum.A >NumberEnum.B : NumberEnum.B >NumberEnum : typeof NumberEnum >B : NumberEnum.B >u === StringEnum.A : boolean ->u : unknown +>u : not NumberEnum.A & not NumberEnum.B >StringEnum.A : StringEnum.A >StringEnum : typeof StringEnum >A : StringEnum.A diff --git a/tsc/testdata/baselines/reference/conformance/weakTypesAndLiterals01.js b/tsc/testdata/baselines/reference/conformance/weakTypesAndLiterals01.js index 62d7468ec1c5e..9c5d4a968c47e 100644 --- a/tsc/testdata/baselines/reference/conformance/weakTypesAndLiterals01.js +++ b/tsc/testdata/baselines/reference/conformance/weakTypesAndLiterals01.js @@ -63,7 +63,21 @@ type WeakTypes = { }; type LiteralsOrWeakTypes = "A" | "B" | WeakTypes; declare let aOrB: "A" | "B"; -declare const f: (arg: LiteralsOrWeakTypes) => "A" | "B" | WeakTypes; -declare const g: (arg: WeakTypes) => WeakTypes; +declare const f: (arg: LiteralsOrWeakTypes) => "B" | { + toLowerCase?(): string; +} | { + toUpperCase?(): string; + otherOptionalProp?: number; +} | ({ + optional?: true; +} & not "A"); +declare const g: (arg: WeakTypes) => { + toLowerCase?(): string; +} | { + toUpperCase?(): string; + otherOptionalProp?: number; +} | ({ + optional?: true; +} & not "A"); declare const h: (arg: LiteralsOrWeakTypes) => LiteralsOrWeakTypes; declare const i: (arg: WeakTypes) => WeakTypes; diff --git a/tsc/testdata/baselines/reference/conformance/weakTypesAndLiterals01.types b/tsc/testdata/baselines/reference/conformance/weakTypesAndLiterals01.types index 28790a089e306..db936dbc86db8 100644 --- a/tsc/testdata/baselines/reference/conformance/weakTypesAndLiterals01.types +++ b/tsc/testdata/baselines/reference/conformance/weakTypesAndLiterals01.types @@ -26,8 +26,8 @@ declare let aOrB: "A" | "B"; >aOrB : "A" | "B" const f = (arg: LiteralsOrWeakTypes) => { ->f : (arg: LiteralsOrWeakTypes) => "A" | "B" | WeakTypes ->(arg: LiteralsOrWeakTypes) => { if (arg === "A") { return arg; } else { return arg; }} : (arg: LiteralsOrWeakTypes) => "A" | "B" | WeakTypes +>f : (arg: LiteralsOrWeakTypes) => "B" | { toLowerCase?(): string; } | { toUpperCase?(): string; otherOptionalProp?: number; } | ({ optional?: true; } & not "A") +>(arg: LiteralsOrWeakTypes) => { if (arg === "A") { return arg; } else { return arg; }} : (arg: LiteralsOrWeakTypes) => "B" | { toLowerCase?(): string; } | { toUpperCase?(): string; otherOptionalProp?: number; } | ({ optional?: true; } & not "A") >arg : LiteralsOrWeakTypes if (arg === "A") { @@ -40,13 +40,13 @@ const f = (arg: LiteralsOrWeakTypes) => { } else { return arg; ->arg : "B" | WeakTypes +>arg : ("B" | WeakTypes) & not "A" } } const g = (arg: WeakTypes) => { ->g : (arg: WeakTypes) => WeakTypes ->(arg: WeakTypes) => { if (arg === "A") { return arg; } else { return arg; }} : (arg: WeakTypes) => WeakTypes +>g : (arg: WeakTypes) => { toLowerCase?(): string; } | { toUpperCase?(): string; otherOptionalProp?: number; } | ({ optional?: true; } & not "A") +>(arg: WeakTypes) => { if (arg === "A") { return arg; } else { return arg; }} : (arg: WeakTypes) => { toLowerCase?(): string; } | { toUpperCase?(): string; otherOptionalProp?: number; } | ({ optional?: true; } & not "A") >arg : WeakTypes if (arg === "A") { @@ -59,7 +59,7 @@ const g = (arg: WeakTypes) => { } else { return arg; ->arg : WeakTypes +>arg : WeakTypes & not "A" } } diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedDiscriminantIntersectionSimplifies.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedDiscriminantIntersectionSimplifies.ts new file mode 100644 index 0000000000000..3e43830741b03 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedDiscriminantIntersectionSimplifies.ts @@ -0,0 +1,84 @@ +// @strict: true +// @noEmit: true + +// When an intersection 'C & not A' has non-negated part 'C' that is mutually exclusive with the +// negated base 'A' by virtue of a shared discriminant property (a property present on both whose +// literal types are disjoint), the 'not A' member is redundant and is dropped, leaving 'C'. + +interface A { + kind: "a"; + field: string; +} +interface B { + kind: "b"; + field: number; +} +interface C { + kind: "c"; + field: object; +} + +declare function wantsC(x: C): void; + +// 'C & not A' -> 'C' because C.kind ("c") is disjoint from A.kind ("a"). +declare const c1: C & not A; +c1; // C +wantsC(c1); + +// Multiple negations, each mutually exclusive with C: 'C & not A & not B' -> 'C'. +declare const c2: C & not A & not B; +c2; // C +wantsC(c2); + +// Non-discriminant negation is retained: 'C & not { other: number }' shares no disjoint discriminant. +declare const c3: C & not { other: number }; +c3; // C & not { other: number; } + +// A negation whose shared property has the SAME discriminant value is retained (not disjoint): +// C.kind and the negated base's kind are both "c", so they are not mutually exclusive. +declare const c4: C & not { kind: "c"; other: number }; +c4; // C & not { kind: "c"; other: number; } + +// Enum discriminants: two distinct string-enum members are mutually exclusive. +enum E { + A = "a", + B = "b", +} +interface EA { + tag: E.A; + payload: string; +} +interface EB { + tag: E.B; + payload: number; +} +declare function wantsEA(x: EA): void; + +// 'EA & not EB' -> 'EA' because E.A and E.B are disjoint enum members. +declare const e1: EA & not EB; +e1; // EA +wantsEA(e1); + +// A string-enum member is a *distinct* type from the bare string literal of its value: 'E.A' and +// '"a"' have an empty intersection ('E.A & "a"' is never), so they are mutually exclusive and the +// negation is dropped. This is precisely the case a by-identity comparison of the property types +// would get wrong -- the regular literal type of 'E.A' is the same '"a"', so identity would treat +// them as overlapping and wrongly keep the negation. The intersection-based check gets it right. +declare const e2: EA & not { tag: "a"; payload: number }; +e2; // EA +wantsEA(e2); + +// The same enum member on both sides is NOT disjoint, so the negation is retained. +declare const e3: EA & not { tag: E.A; extra: number }; +e3; // EA & not { tag: E.A; extra: number; } + +// A union-of-literals discriminant: '"a" | "b"' is disjoint from '"c" | "d"', so the negation is +// dropped even though neither side is a single unit type (a by-identity check would miss this). +interface P { + kind: "a" | "b"; + p: string; +} +declare const u1: P & not { kind: "c" | "d"; p: number }; +u1; // P + + diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedFreshTreatedAsClosedSet.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedFreshTreatedAsClosedSet.ts new file mode 100644 index 0000000000000..2dc66bfab8deb --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedFreshTreatedAsClosedSet.ts @@ -0,0 +1,10 @@ +// from https://github.com/Microsoft/TypeScript/issues/4183 +type Distinct = (A | B) & not (A & B); +declare var o1: {x: any}; +declare var o2: {y: any}; + +declare function f1(x: Distinct): void; + +f1({x: 0}); // OK +f1({y: 0}); // OK +f1({x: 0, y: 0}); // Should error diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedInMappedTypeDisablesExcessProperties.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedInMappedTypeDisablesExcessProperties.ts new file mode 100644 index 0000000000000..0526970fea9b3 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedInMappedTypeDisablesExcessProperties.ts @@ -0,0 +1,23 @@ +// https://github.com/Microsoft/TypeScript/issues/4196 +// needs https://github.com/Microsoft/TypeScript/pull/26797 to work, as even though the mapped type can be +// written, the key type `string & ~("foo" | "bar")` can't be represented as properties or string/number index +// signatures + +type Config = { + foo: number; + bar: number; +} & { + [k in (string & not ("foo" | "bar"))]: string; +}; + +const conf: Config = { + foo: 12, + bar: 12, + other: "string" +}; // OK + +const conf2: Config = { + foo: 12, + bar: 12, + other: 0, +}; // Should error diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingAssertion.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingAssertion.ts new file mode 100644 index 0000000000000..5a23e75ef40c1 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingAssertion.ts @@ -0,0 +1,38 @@ +// @strict: true +// @noEmit: true + +// Assertion signatures narrow only the (single) continuation after the call. Because there is no +// `false` branch, no fresh CFA negation is introduced; a negation only appears when the assertion +// predicate itself is written with `not`. + +interface Cat { + meow(): void; +} + +declare function assertCat(x: unknown): asserts x is Cat; +declare function assertNotCat(x: unknown): asserts x is not Cat; +declare function assertDefined(x: T): asserts x is NonNullable; +declare function assertTruthy(x: unknown): asserts x; + +declare function wantsNotCat(x: not Cat): void; + +// `asserts x is Cat` narrows to Cat. +declare const a: {}; +assertCat(a); +a; // {} & Cat + +// `asserts x is not Cat` narrows to `not Cat` (the negation comes from the annotation). +declare const b: {}; +assertNotCat(b); +b; // {} & not Cat +wantsNotCat(b); + +// `asserts x is NonNullable` removes null/undefined without introducing a negation. +declare const c: string | undefined; +assertDefined(c); +c; // string + +// `asserts x` (truthiness assertion) removes falsy constituents, no negation. +declare const d: {} | undefined | 0; +assertTruthy(d); +d; // {} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingEquality.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingEquality.ts new file mode 100644 index 0000000000000..b6968eb2e1fe9 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingEquality.ts @@ -0,0 +1,48 @@ +// @strict: true +// @noEmit: true + +// Direct equality comparisons (`===`, `!==`, `==`, `!=`) to `undefined`, `null`, and literal values +// narrow via type facts and constituent filtering. They do NOT introduce fresh `not` negations, so +// these baselines act as a guard that negations only come from typeof / instanceof / type guards. + +declare function wantsNotUndef(x: not undefined): void; + +// `=== undefined` removes undefined; the else branch is just `{}` (no `not undefined`). +declare const a: {} | undefined; +if (a === undefined) { + a; // undefined +} else { + a; // {} +} + +// `!== null` in strict mode. +declare const b: {} | null; +if (b !== null) { + b; // {} +} else { + b; // null +} + +// Literal comparison filters the matching constituent; the else branch keeps the rest unchanged. +declare const c: "foo" | "bar" | {}; +if (c === "foo") { + c; // "foo" +} else { + c; // "bar" | {} +} + +// `== null` (double equals) removes both null and undefined. +declare const d: {} | null | undefined; +if (d == null) { + d; // null | undefined +} else { + d; // {} +} + +// Numeric literal comparison on a `{}` base leaves `{}` unrefined in the else branch. +declare const e: {}; +if (e === 0) { + e; // {} (0 is comparable to {}) +} else { + e; // {} +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingEqualityLiteral.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingEqualityLiteral.ts new file mode 100644 index 0000000000000..d1818f0e26737 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingEqualityLiteral.ts @@ -0,0 +1,51 @@ +// @strict: true +// @noEmit: true + +// The false branch of a literal equality comparison introduces a negated type, so a base type that +// overlaps the compared value records the exclusion (e.g. 'number & not 0'). + +declare function wantsNonZero(x: number & not 0): void; +declare function wantsZero(x: 0): void; + +declare const n: number; +if (n === 0) { + wantsZero(n); // 0 +} else { + n; // number & not 0 + wantsNonZero(n); +} + +// `!==` flips the branches. +declare const m: number; +if (m !== 0) { + m; // number & not 0 + wantsNonZero(m); +} else { + wantsZero(m); // 0 +} + +// A disjoint union member: 'not 0' is redundant against non-overlapping constituents. +declare const u: 0 | 1 | 2; +if (u === 0) { + u; // 0 +} else { + u; // 1 | 2 +} + +// A string base is disjoint from the numeric literal, so the negation reduces away. +declare const s: string; +if ((s as unknown) === 0) { + s; // string +} else { + s; // string +} + +// String literal comparison on a broad base. +declare function wantsNotFoo(x: string & not "foo"): void; +declare const str: string; +if (str === "foo") { + str; // "foo" +} else { + str; // string & not "foo" + wantsNotFoo(str); +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingInOperator.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingInOperator.ts new file mode 100644 index 0000000000000..d1125a8a3d869 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingInOperator.ts @@ -0,0 +1,41 @@ +// @strict: true +// @noEmit: true + +// The `in` operator narrows by presence/absence of a property. It uses type facts and constituent +// filtering (not fresh `not` negations), so the else branch keeps the property-absent constituents. + +declare function wantsNotHasA(x: not { a: unknown }): void; + +interface WithA { + a: number; +} +interface WithB { + b: string; +} + +declare const a: WithA | WithB; +if ("a" in a) { + a; // WithA +} else { + a; // WithB +} + +// `in` on a `{}` base does not synthesize a negation; the true branch records the tested member. +declare const b: {}; +if ("a" in b) { + b; // Record<"a", unknown> +} else { + b; // {} +} + +// Optional property discrimination. +interface Maybe { + kind: "maybe"; + payload?: string; +} +declare const c: Maybe; +if ("payload" in c) { + c; // Maybe +} else { + c; // Maybe +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingInstanceof.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingInstanceof.ts new file mode 100644 index 0000000000000..0a7c5271af512 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingInstanceof.ts @@ -0,0 +1,74 @@ +// @strict: true +// @noEmit: true + +// `instanceof` narrowing is nominal (prototype-based), so it deliberately does NOT introduce a +// structural `not C` in the false branch. Class types frequently lack nominal tags and are structural +// subtypes of one another, so a structural negation would unsoundly reduce nominally-distinct +// constituents to `never`. This file guards that instanceof narrows by filtering only. + +class Animal { + move(): void {} +} +class Dog extends Animal { + bark(): void {} +} + +// A broad base is narrowed on the true branch but left intact (no `not Dog`) on the false branch. +declare const a: object; +if (a instanceof Dog) { + a; // Dog +} else { + a; // object +} + +declare const b: {}; +if (b instanceof Dog) { + b; // Dog +} else { + b; // {} +} + +// A supertype base keeps the whole supertype (no `not Dog`). +declare const c: Animal; +if (c instanceof Dog) { + c; // Dog +} else { + c; // Animal +} + +// A bare type parameter: true branch intersects, false branch is unchanged. +function generic(x: T) { + if (x instanceof Dog) { + x; // T & Dog + } else { + x; // T + } +} + +// Structurally-related but nominally-distinct classes must both survive: `Derived2` structurally +// extends `Derived1`, but a `Derived2` instance is not `instanceof Derived1`, so the else branch +// must keep `Derived2` (it must NOT collapse to `never`). +class Base { + basey = ""; +} +class Derived1 extends Base { + d = ""; +} +class Derived2 extends Base { + d = ""; + other = ""; +} +declare const e: Derived1 | Derived2; +if (e instanceof Derived1) { + e; // Derived1 +} else { + e; // Derived2 +} + +// A disjoint object constituent is dropped on the true branch and kept on the false branch. +declare const d: Dog | { kind: "other" }; +if (d instanceof Dog) { + d; // Dog +} else { + d; // { kind: "other"; } +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingSwitchTrue.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingSwitchTrue.ts new file mode 100644 index 0000000000000..2b54a5b0184d8 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingSwitchTrue.ts @@ -0,0 +1,55 @@ +// @strict: true +// @noEmit: true + +// `switch (true)` narrowing evaluates each case's condition against the reference. Each subsequent +// case sees the negation of the preceding conditions. This exercises the interaction between the +// fresh CFA negations introduced by instanceof/typeof and the switch-on-true clause narrowing. + +class A { + a = 1; +} +class B { + b = 2; +} +class C { + c = 3; +} + +declare const x: A | B | C; +switch (true) { + case x instanceof A: + x; // A + break; + case x instanceof B: + x; // B + break; + default: + x; // C +} + +// typeof-based switch(true). +declare const y: {}; +switch (true) { + case typeof y === "string": + y; // string + break; + case typeof y === "number": + y; // number + break; + default: + y; // {} & not string & not number +} + +// A guard-based switch(true). +interface Cat { + meow(): void; +} +declare function isCat(v: unknown): v is Cat; +declare const z: {}; +switch (true) { + case isCat(z): + z; // {} & Cat + break; + default: + z; // {} & not Cat +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingSwitchTypeof.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingSwitchTypeof.ts new file mode 100644 index 0000000000000..38b9393535f69 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingSwitchTypeof.ts @@ -0,0 +1,40 @@ +// @strict: true +// @noEmit: true + +// `switch (typeof x)` narrowing. Each case narrows to the primitive; the `default` clause is the +// negation of all handled primitives. + +declare function wantsNotStr(x: not string): void; + +declare const a: {}; +switch (typeof a) { + case "string": + a; // string + break; + case "number": + a; // number + break; + default: + a; // {} & not string & not number (default excludes handled primitives) +} + +// A single handled case: default excludes just that primitive. +declare const b: {}; +switch (typeof b) { + case "string": + b; // string + break; + default: + b; // {} & not string + wantsNotStr(b); +} + +// Disjoint union: default reduces to the unhandled constituents with no lingering negation. +declare const c: string | number | boolean; +switch (typeof c) { + case "string": + c; // string + break; + default: + c; // number | boolean +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingTruthiness.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingTruthiness.ts new file mode 100644 index 0000000000000..58858d8452dc0 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingTruthiness.ts @@ -0,0 +1,36 @@ +// @strict: true +// @noEmit: true + +// Truthiness narrowing removes falsy constituents (0, "", null, undefined, false, NaN) via type +// facts. It does not introduce fresh `not` negations. + +declare const a: {} | undefined | null; +if (a) { + a; // {} +} else { + a; // undefined | null +} + +declare const b: string | 0 | undefined; +if (b) { + b; // string (definitely-falsy 0 and undefined removed; no negation introduced) +} else { + b; // string | 0 | undefined (no `not` synthesized) +} + +// Truthiness on a bare `{}` leaves it unchanged on both branches: the empty object type includes +// falsy primitives (0, "", false, ...), so it is not reduced to `never` in the else branch. +declare const c: {}; +if (c) { + c; // {} +} else { + c; // {} +} + +// Negation via `!` flips the branches. +declare const d: number | undefined; +if (!d) { + d; // 0 | undefined +} else { + d; // number +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingTypePredicate.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingTypePredicate.ts new file mode 100644 index 0000000000000..a0110a8ab8eb1 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingTypePredicate.ts @@ -0,0 +1,52 @@ +// @strict: true +// @noEmit: true + +// Control flow narrowing by a user-defined type guard `x is T`. In the false branch a fresh +// `not T` is intersected in and survives where the base type overlaps T. + +interface Cat { + meow(): void; +} + +declare function isCat(x: unknown): x is Cat; +declare function wantsNotCat(x: not Cat): void; + +// `{}` base overlaps Cat. +declare const a: {}; +if (isCat(a)) { + a; // {} & Cat +} else { + a; // {} & not Cat + wantsNotCat(a); +} + +// A bare type parameter. +function generic(x: T) { + if (isCat(x)) { + x; // T & Cat + } else { + x; // T & not Cat + } +} + +// A disjoint union: `not Cat` reduces away against the non-Cat constituent. +interface Dog { + bark(): void; + meow?: undefined; +} +declare const b: Cat | Dog; +if (isCat(b)) { + b; // Cat +} else { + b; // Dog +} + +// A negated type guard `x is not Cat` narrows the *true* branch to `not Cat`. +declare function isNotCat(x: unknown): x is not Cat; +declare const c: {}; +if (isNotCat(c)) { + c; // {} & not Cat + wantsNotCat(c); +} else { + c; // {} & Cat +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingTypeof.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingTypeof.ts new file mode 100644 index 0000000000000..ea2573f3c39b2 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedNarrowingTypeof.ts @@ -0,0 +1,59 @@ +// @strict: true +// @noEmit: true + +// Control flow narrowing by `typeof x === "..."`. In the false branch a fresh `not ` +// is intersected in, but only survives where the base type overlaps the removed primitive. + +declare function wantsNotStr(x: not string): void; +declare function wantsNotNum(x: not number): void; + +// `{}` overlaps every primitive, so the negation is retained. +declare const a: {}; +if (typeof a === "string") { + a; // string +} else { + a; // {} & not string + wantsNotStr(a); +} + +// `!==` flips the branches. +declare const b: {}; +if (typeof b !== "number") { + b; // {} & not number + wantsNotNum(b); +} else { + b; // number +} + +// A disjoint union: `not number` is redundant and reduces away. +declare const c: string | number; +if (typeof c === "number") { + c; // number +} else { + c; // string +} + +// A bare type parameter retains the negation on each branch. +function generic(x: T) { + if (typeof x === "boolean") { + x; // T & boolean + } else { + x; // T & not boolean + } +} + +// `unknown` narrows to the primitive on the true branch and keeps a negation on the false branch. +declare const u: unknown; +if (typeof u === "string") { + u; // string +} else { + u; // (unknown narrowed) & not string +} + +// `==` / `!=` behave like their strict counterparts here. +declare const d: {}; +if (typeof d == "bigint") { + d; // bigint +} else { + d; // {} & not bigint +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedPromiseRepr.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedPromiseRepr.ts new file mode 100644 index 0000000000000..0e402b6716266 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedPromiseRepr.ts @@ -0,0 +1,52 @@ +// @target: es6 +// inspired by a comment in https://github.com/Microsoft/TypeScript/issues/4196 + +type AnyPromiseLikeObject = object & MyPromiseLike; +interface MyPromiseLike { + then(onResolve: (value: T) => any, onReject: (error: E) => any): any; +} + +type AwaitValue = T extends MyPromiseLike ? U : T; + +type CoercePromiseLike = MyPromise ? AwaitValue : T, never>; + +interface MyPromiseConstructor { + resolve(value: T): CoercePromiseLike; + reject(value: E): MyPromise; + all(values: Iterable): MyPromise[] & not AnyPromiseLikeObject, E>; + race(values: Iterable): MyPromise, E>; +} +declare var MyPromise: MyPromiseConstructor; + +interface MyPromise { + then(onResolve?: not Function, onReject?: not Function): MyPromise; + catch(onReject?: not Function): MyPromise; + then( + onResolve: (value: AwaitValue) => U, + onReject?: not Function, + ): MyPromise, E | F>; + then( + onResolve: not Function, + onReject: (error: E) => U, + ): MyPromise, F>; + then( + onResolve: (value: AwaitValue) => U, + onReject: (error: E) => AwaitValue, + ): MyPromise, F>; + catch( + onReject: (error: E) => U, + ): MyPromise, F>; + finally(onSettled: () => AnyPromiseLikeObject): MyPromise; +} + +const a = MyPromise.resolve(0); + +const b = MyPromise.resolve(MyPromise.resolve(0)); + +const d = MyPromise.resolve(MyPromise.resolve(MyPromise.resolve(0))); + +const e = MyPromise.resolve(0).then(x => "ok"); + +const f = MyPromise.all([1, 2, 3, Promise.resolve("ok")]); + +const g = MyPromise.race([1, 2, 3, Promise.resolve("ok")]); diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedRepresentativeExamples.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedRepresentativeExamples.ts new file mode 100644 index 0000000000000..51d2c91b82c74 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedRepresentativeExamples.ts @@ -0,0 +1,33 @@ +// @strict: true +// https://github.com/Microsoft/TypeScript/issues/7993 + +declare function ignore)>(value: T): void; +declare function readFileAsync(): Promise; +declare function readFileSync(): string; +ignore(readFileSync()); // OK +ignore(readFileAsync()); // Should error + +declare function map(values: T[], map: (value: T) => U) : U[]; // validate map callback doesn't return void + +function foo() {} + +map([1, 2, 3], n => n + 1); // OK +map([1, 2, 3], foo); // Should error + +function asValid(value: T, isValid: (value: T) => boolean) : T | null { + return isValid(value) ? value : null; +} + +declare const x: number; +declare const y: number | null; +asValid(x, n => n >= 0); // OK +asValid(y, n => n >= 0); // Should error + +function tryAt(values: T[], index: number): T | undefined { + return values[index]; +} + +declare const a: number[]; +declare const b: (number | undefined)[]; +tryAt(a, 0); // OK +tryAt(b, 0); // Should error diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypeAppliesToFalseBranchOfConditional.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypeAppliesToFalseBranchOfConditional.ts new file mode 100644 index 0000000000000..b844edcbd2e82 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypeAppliesToFalseBranchOfConditional.ts @@ -0,0 +1,5 @@ +// https://github.com/Microsoft/TypeScript/issues/26240 + +type OnlyNumber = T; +type ToNumber = + T extends string ? undefined : OnlyNumber; diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypes.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypes.ts new file mode 100644 index 0000000000000..a29212af093cc --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypes.ts @@ -0,0 +1,109 @@ +enum Literal { + ok = "ok" +} + +enum NumLiteral { + Val +} + +function f1( + notString: not string, + str: string, + strlit: "ok", + strenum: Literal, + num: number, + numlit: 0, + numenum: NumLiteral, + unknownVal: unknown, + neverVal: never +) { + notString = str; // not ok + notString = strlit; // not ok + notString = strenum; // not ok + notString = num; // ok + notString = numlit; // ok + notString = numenum; // ok + notString = unknownVal; // not ok (unknown is all values, includes string) + notString = neverVal; // ok (never is empty set of types, doesn't include string) + + str = notString; // not ok + strlit = notString; // not ok + strenum = notString; // not ok + num = notString; // not ok + numlit = notString; // not ok + numenum = notString; // not ok + unknownVal = notString; // ok + neverVal = notString; // not ok +} + +function f2( + x: { x: any }, + y: { y: any }, + xy: { x: any, y: any }, + nx: not typeof x, + ny: not typeof y, + nxy: not typeof xy, + neither: not (typeof x | typeof y), + notBoth: not (typeof x & typeof y) +) { + x = y; // not ok + x = xy; // ok + x = nx; // not ok + x = ny; // not ok + x = nxy; // not ok + x = neither; // not ok + x = notBoth; // not ok + + y = x; // not ok + y = xy; // ok + y = nx; // not ok + y = ny; // not ok + y = nxy; // not ok + y = neither; // not ok + y = notBoth; // not ok + + xy = x; // not ok + xy = y; // not ok + xy = nx; // not ok + xy = ny; // not ok + xy = nxy; // not ok + xy = neither; // not ok + xy = notBoth; // not ok + + nx = x; // not ok + nx = y; // not ok + nx = ny; // not ok + nx = nxy; // not ok + nx = neither; // ok + nx = notBoth; // not ok + + ny = x; // not ok + ny = y; // not ok + ny = nx; // not ok + ny = nxy; // not ok + ny = neither; // ok + ny = notBoth; // not ok + + nxy = x; // not ok + nxy = y; // not ok + nxy = xy; // not ok + nxy = nx; // ok + nxy = ny; // ok + nxy = neither; // ok + nxy = notBoth; // ok + + neither = x; // not ok + neither = y; // not ok + neither = xy; // not ok + neither = nx; // not ok + neither = ny; // not ok + neither = nxy; // not ok + neither = notBoth; // not ok + + notBoth = x; // not ok + notBoth = y; // not ok + notBoth = xy; // not ok + notBoth = nx; // ok + notBoth = ny; // ok + notBoth = neither; // ok +} \ No newline at end of file diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesContravariantInference.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesContravariantInference.ts new file mode 100644 index 0000000000000..ea4ae2b0998cb --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesContravariantInference.ts @@ -0,0 +1,42 @@ +// @strict: true +// @noEmit: true + +// Demonstrates why inference through the `not` operator must be contravariant. +// +// `T` appears only in `not T` positions and receives one candidate from each argument: +// `{ a: number }` and `{ a: number; b: number }`. Note the second is a *subtype* of the +// first. +// +// For the call to be well-typed, both `Box` and `Box` must be assignable to +// `Box`. Since `not` reverses subtyping, `not A <: not T` requires `T <: A`, and +// likewise `T <: B`. So `T` must be a common *subtype* of the two operands, i.e. the more +// specific `{ a: number; b: number }`. Contravariant inference produces exactly this by +// combining candidates with `getCommonSubtype`. +// +// Covariant inference would instead combine them with `getCommonSupertype`, yielding the +// wider `{ a: number }`. That `T` is not assignable back into the `Box` +// parameter (it would require `{ a } <: { a; b }`, which is false), so the call would fail +// and `r.b` would be inaccessible. + +interface Box { value: T; } + +declare function combine(x: Box, y: Box): T; + +declare const boxNotA: Box; +declare const boxNotAB: Box; + +// Contravariant inference: T = { a: number; b: number } (the common subtype). +const r = combine(boxNotA, boxNotAB); + +r.a; // ok +r.b; // ok only because contravariant inference chose the subtype; covariant would pick { a } and error here + +// The same effect with plain (non-wrapped) negated parameters. +declare function combineBare(x: not T, y: not T): T; +declare const notA: not { a: number }; +declare const notAB: not { a: number; b: number }; + +const r2 = combineBare(notA, notAB); // T = { a: number; b: number } + +r2.a; // ok +r2.b; // ok only with contravariant inference diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesControlFlow.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesControlFlow.ts new file mode 100644 index 0000000000000..8d4ffb19e3b46 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesControlFlow.ts @@ -0,0 +1,19 @@ +interface A { type: "a", data: number } +interface B { type: "b", data: string } +interface Unknown { type: string & not ("a"|"b"), data: object } +type ABU = A | B | Unknown; +declare function needsNumber(x: number): void; +declare function needsString(x: string): void; +declare function needsObject(x: object): void; +declare var x: ABU; + +if (x.type === "a") { + let y = x.data; + needsNumber(y); +} +else if (x.type === "b") { + needsString(x.data); +} +else { + needsObject(x.data); +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesControlFlowNarrowing.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesControlFlowNarrowing.ts new file mode 100644 index 0000000000000..7f80ab8de41a2 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesControlFlowNarrowing.ts @@ -0,0 +1,46 @@ +// @strict: true +// @noEmit: true + +// Control flow narrowing introduces negated types in the false branch of a narrowing check. +// The negation is only retained where it is non-redundant (i.e. the narrowed base type overlaps +// the removed candidate, such as `{}` / `unknown`); for ordinary disjoint unions it reduces away. + +declare function wantsStr(x: string): void; +declare function wantsNotStr(x: not string): void; +declare function wantsNegatedCallbackResult(cb: () => not string): void; + +const item = {}; + +if (typeof item === "string") { + wantsStr(item); // item: string +} else { + wantsNotStr(item); // item: {} & not string + // The negation also flows through an arrow function body (a position a syntactic check misses). + wantsNegatedCallbackResult(() => item); // item: {} & not string +} + +// No negation is introduced against a disjoint union: 'not number' reduces away. +declare const value: string | number; +if (typeof value === "string") { + value; // string +} else { + value; // number +} + +// Union base where the negation is redundant against every constituent. +declare function wantsNotNum(x: not number): void; +declare const u: string | number | boolean; +if (typeof u === "number") { + u; // number +} else { + wantsNotNum(u); // string | boolean +} + +// The value flows into a negated position nested inside an object literal argument. +declare function wantsNestedNegated(x: { member: not string }): void; +declare const nested: {}; +if (typeof nested === "string") { + nested; // string +} else { + wantsNestedNegated({ member: nested }); // nested: {} & not string +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesDeMorgan.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesDeMorgan.ts new file mode 100644 index 0000000000000..b75360c51bd29 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesDeMorgan.ts @@ -0,0 +1,40 @@ +// @strict: true +// @noEmit: true + +// De Morgan behavior and union/intersection interaction for negated types. + +type A = { a: number }; +type B = { b: number }; + +// not (A | B) is distributed to not A & not B. +type NotAorB = not (A | B); + +// not (A & B) stays as a single negation of the intersection. +type NotAandB = not (A & B); + +// A union of negations (not simplified by De Morgan in this direction). +type NotAorNotB = not A | not B; + +// An intersection of negations equals the negation of the union. +type NotAandNotB = not A & not B; + +// Primitive forms. +type NotStringOrNumber = not (string | number); // not string & not number +type NotStringAndNever = not string | not never; // not never => unknown, so union widens + +// Assignability relationships between the forms. +declare let notAorB: NotAorB; // not A & not B +declare let notAandNotB: NotAandNotB; // not A & not B + +notAorB = notAandNotB; // should be ok (same type) +notAandNotB = notAorB; // should be ok (same type) + +declare let notAorNotB: NotAorNotB; // not A | not B +notAorB = notAorNotB; // relationship probe +notAorNotB = notAorB; // relationship probe + +// Concrete values against the distributed intersection. +declare let ab: A & B; +declare let aOnly: A; +notAorB = ab; // probe: A & B excluded by both negations? +notAorB = aOnly; // probe: A excluded by not A diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesDeclarationEmit.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesDeclarationEmit.ts new file mode 100644 index 0000000000000..fa7a8ee3a5ff0 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesDeclarationEmit.ts @@ -0,0 +1,28 @@ +// @strict: true +// @declaration: true + +// Declaration emit round-trip for negated types. +// Each exported declaration should print its `not` type faithfully in the .d.ts. + +export type NotString = not string; + +export type NotUnionOfLiterals = not ("a" | "b" | "c"); + +export type NotObject = not { x: number }; + +export declare let notNumber: not number; + +export declare function accept(x: not null): void; + +export declare function make(value: T): T; + +export interface Holder { + value: not boolean; + readonly tag: string & not "reserved"; +} + +export type IndexNoMethod = { + [idx: string & not "method"]: number; +}; + +export declare const nested: not (string | { y: not number }); diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesGenericInference.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesGenericInference.ts new file mode 100644 index 0000000000000..7ccbab741c7bf --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesGenericInference.ts @@ -0,0 +1,32 @@ +// @strict: true +// @noEmit: true + +// Generic inference from `not T` positions. + +interface Box { value: T; } + +// Inferring a type argument from a bare negated parameter position. +declare function fromNot(x: not T): T; +const r1 = fromNot("literal is irrelevant here"); // explicit T = string +declare const numVal: number; +const r2 = fromNot(numVal); // T can't be inferred from a bare `not T` when the argument isn't negated -> unknown -> never (error) + +// Inferring from a negated type nested inside a generic wrapper. +declare function fromBoxNot(x: Box): T; +declare const boxNotString: Box; +const r3 = fromBoxNot(boxNotString); // T is inferred as string + +// Inferring from a negated intersection. +declare function fromStringNot(x: string & not T): T; +declare const sv: string & not "bar"; +const r4 = fromStringNot(sv); // T is inferred as "bar" + +// Inference site where the same T appears both negated and positive. +declare function both(a: T, b: not T): T; +const r5 = both("hello", 123); // T = "hello" from the first arg; 123 checked against not "hello" + +// Higher-order: mapping a negated type parameter. +type Negate = not T; +declare function viaAlias(x: Negate): T; +declare const nv: not number; +const r6 = viaAlias(nv); // T is inferred as number diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInConditionalTypesAndInfer.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInConditionalTypesAndInfer.ts new file mode 100644 index 0000000000000..8514fad7d88ba --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInConditionalTypesAndInfer.ts @@ -0,0 +1,31 @@ +// @strict: true +// @noEmit: true + +// Negated types combined with conditional types and `infer`. + +// A conditional that tests assignability to a negated type. +type IsNotString = T extends not string ? true : false; +type A1 = IsNotString; // number is not a string -> true +type A2 = IsNotString<"hello">; // a string literal -> false +type A3 = IsNotString; // an object -> true + +// Distributive conditional producing negated types in a branch. +type Branch = T extends string ? T : not T; +type B1 = Branch; // string +type B2 = Branch; // not number +type B3 = Branch; // distributes: string | not number + +// `infer` underneath the `not` operator. +type InferUnderNot = T extends not (infer U) ? U : never; +type C1 = InferUnderNot; // infer binds U = string +type C2 = InferUnderNot; // number is not a negated type -> false branch -> never + +// `infer` capturing a negated type. +type InferNegated = T extends Box ? U : never; +interface Box { value: T; } +type D1 = InferNegated>; // U should be not string + +// Conditional constraint using not. +type NonNullish = T extends not (null | undefined) ? T : never; +type E1 = NonNullish; // distributes to string +type E2 = NonNullish; // never diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInIndexSignatures.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInIndexSignatures.ts new file mode 100644 index 0000000000000..59df72a98071f --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInIndexSignatures.ts @@ -0,0 +1,49 @@ +// @strict: true +// @noEmit: true + +// Negated types used to build index signature key types. + +// The canonical example: a string index that excludes a specific key. +type NoMethod = { + [idx: string & not "method"]: number; +}; + +declare let noMethod: NoMethod; +noMethod.foo = 1; // ok +noMethod.method = 1; // excluded key +noMethod["bar"] = 2; // ok + +// Excluding a union of keys. +type NoAB = { + [idx: string & not ("a" | "b")]: number; +}; + +declare let noAB: NoAB; +noAB.c = 1; // ok +noAB.a = 1; // excluded key +noAB.b = 1; // excluded key + +// Mapped-type form that produces the same key type. +type Config = { + foo: number; + bar: number; +} & { + [k in (string & not ("foo" | "bar"))]: string; +}; + +const conf: Config = { + foo: 12, + bar: 12, + other: "string", +}; // ok + +const conf2: Config = { + foo: 12, + bar: 12, + other: 0, +}; // other should be a string + +// A bare negated type as an index key (not intersected with string). +type BareNegated = { + [idx: not "method"]: number; +}; diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInKeyofAndMappedKeyRemapping.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInKeyofAndMappedKeyRemapping.ts new file mode 100644 index 0000000000000..556fe994995df --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInKeyofAndMappedKeyRemapping.ts @@ -0,0 +1,49 @@ +// @strict: true +// @noEmit: true + +// Negated types combined with keyof and mapped-type key remapping (`as`). + +interface Obj { + id: number; + name: string; + method(): void; +} + +// keyof over the object. +type K = keyof Obj; // "id" | "name" | "method" + +// Negation of a keyof union. +type NotKeyof = not keyof Obj; // not ("id" | "name" | "method") + +// keyof applied to a negated object type. +type KeyofNot = keyof (not Obj); + +// Key remapping that filters out a specific key via `as (K & not "id")`. +type WithoutId = { + [P in keyof Obj as (P & not "id")]: Obj[P]; +}; + +// Key remapping that filters out several keys. +type OnlyData = { + [P in keyof Obj as (P & not ("id" | "method"))]: Obj[P]; +}; + +// Probes against the remapped types. +declare let withoutId: WithoutId; +withoutId.name; // should exist +withoutId.method; // should exist +withoutId.id; // should be removed + +declare let onlyData: OnlyData; +onlyData.name; // should exist +onlyData.id; // should be removed +onlyData.method; // should be removed + +// Generic key filtering. +type Omit2 = { + [P in keyof T as (P & not K)]: T[P]; +}; +type ObjNoName = Omit2; +declare let objNoName: ObjNoName; +objNoName.id; // should exist +objNoName.name; // should be removed diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralMatching.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralMatching.ts new file mode 100644 index 0000000000000..0fcbc74853a7d --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralMatching.ts @@ -0,0 +1,42 @@ +// @strict: true +// @noEmit: true + +// Matching actual string literal types against pattern literal types that +// contain negated holes. `"foobaz"` should match `foo${string & not "bar"}` +// but `"foobar"` should not, because the hole excludes exactly "bar". + +type Pattern = `foo${string & not "bar"}`; + +// Direct assignment of literals to the pattern type. +declare let pat: Pattern; +pat = "foobaz"; // should be ok +pat = "foobar"; // should error +pat = "foo"; // should be ok (the hole can match the empty string) +pat = "baz"; // should error (missing "foo" prefix) + +// Assignability from a literal-typed value. +declare const foobaz: "foobaz"; +declare const foobar: "foobar"; +pat = foobaz; // should be ok +pat = foobar; // should error + +// Matching via a conditional type (extends check). +type MatchFoobaz = "foobaz" extends Pattern ? true : false; // should be true +type MatchFoobar = "foobar" extends Pattern ? true : false; // should be false + +// Matching a union of literals: only the members that don't collapse the hole +// to never should be retained. +type FilterMatches = T extends Pattern ? T : never; +type Filtered = FilterMatches<"foobaz" | "foobar" | "fooqux">; // should be "foobaz" | "fooqux" + +// Inference through a generic function whose parameter is the pattern. +declare function take(s: `foo${T & not "bar"}`): T; +const okBaz = take("foobaz"); // should be ok, T = "baz" +const errBar = take("foobar"); // should error, "bar" is excluded + +// Excluding a union of holes. +type Pattern2 = `foo${string & not ("bar" | "qux")}`; +declare let pat2: Pattern2; +pat2 = "foobaz"; // should be ok +pat2 = "foobar"; // should error +pat2 = "fooqux"; // should error diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiterals.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiterals.ts new file mode 100644 index 0000000000000..707519f45c4c7 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiterals.ts @@ -0,0 +1,37 @@ +// @strict: true +// @noEmit: true + +// Negated types used as placeholders inside template/pattern literal types. + +// A negated string literal as a placeholder. +type NotBar = `foo${not "bar"}`; + +// A negated primitive as a placeholder. +type NotString = `foo${not string}`; +type NotNumber = `id-${not 0}`; + +// A negated union as a placeholder. +type NotAB = `x-${not ("a" | "b")}`; + +// A negated type intersected with a string, which restricts to string values. +type StringNotBar = `foo${string & not "bar"}`; + +// A generic negated placeholder. +type Wrap = `foo${T & not "bar"}`; +type WrapString = Wrap; +type WrapLiteral = Wrap<"baz">; +type WrapBar = Wrap<"bar">; + +// Assignability against a plainly-typed string. +declare let notBar: NotBar; +declare let stringNotBar: StringNotBar; + +notBar = "foobaz"; // depends on representation +notBar = "foobar"; // depends on representation +stringNotBar = "foobaz"; // depends on representation +stringNotBar = "foobar"; // depends on representation + +// Inference from a template literal pattern with a negated placeholder. +declare function parse(s: `foo${T & not "bar"}`): T; +const p1 = parse("foobaz"); +const p2 = parse("foobar"); diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsAndIndexSignatures.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsAndIndexSignatures.ts new file mode 100644 index 0000000000000..0c2a358141c8b --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsAndIndexSignatures.ts @@ -0,0 +1,31 @@ +// @strict: true +// @noEmit: true + +// Combination: negated types with BOTH pattern literal types and index signatures. + +// Index signature whose key is a template literal containing a negated placeholder. +type TemplateKey = { + [idx: `foo${string & not "bar"}`]: number; +}; + +declare let templateKey: TemplateKey; +templateKey["foobaz"] = 1; // matches pattern +templateKey["foobar"] = 1; // excluded by negation +templateKey["baz"] = 1; // does not match pattern + +// Index signature whose key is a bare negated template literal. +type NotTemplateKey = { + [idx: not `foo${string}`]: number; +}; + +// Mapped type over a template literal key type that uses a negated placeholder. +type MappedTemplate = { + [k in `foo${string & not "bar"}`]: number; +}; + +// Generic index signature combination. +type WrapKey = { + [idx: `foo${T & not "bar"}`]: number; +}; +type WrapKeyString = WrapKey; +type WrapKeyLiteral = WrapKey<"baz">; diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsAndStringMapping.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsAndStringMapping.ts new file mode 100644 index 0000000000000..31a012d116d67 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsAndStringMapping.ts @@ -0,0 +1,31 @@ +// @strict: true +// @noEmit: true + +// Combination: negated types with BOTH pattern literal types and string mapping types. + +// String mapping wrapping a template literal that contains a negated placeholder. +type UpperTemplate = Uppercase<`foo${string & not "bar"}`>; + +// Template literal whose placeholder is a string mapping of a negated type. +type TemplateUpper = `foo${Uppercase}`; + +// Template literal whose placeholder is a negation of a string mapping type. +type TemplateNotUpper = `foo${not Uppercase<"BAR">}`; + +// Negation of a template literal that contains a string mapping placeholder. +type NotTemplateUpper = not `foo${Uppercase}`; + +// Generic composition. +type Compose = Uppercase<`foo${T & not "bar"}`>; +type ComposeString = Compose; +type ComposeLiteral = Compose<"baz">; +type ComposeBar = Compose<"bar">; + +// Assignability probes. +declare let upperTemplate: UpperTemplate; +declare let templateUpper: TemplateUpper; + +upperTemplate = "FOOBAZ"; // depends on representation +upperTemplate = "foobaz"; // depends on representation +templateUpper = "fooBAZ"; // depends on representation +templateUpper = "foobar"; // depends on representation diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts new file mode 100644 index 0000000000000..526b6a0c8165e --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInPatternLiteralsStringMappingAndIndexSignatures.ts @@ -0,0 +1,35 @@ +// @strict: true +// @noEmit: true + +// Combination: negated types with pattern literal types, string mapping types, AND index signatures. + +// Index signature whose key is a string mapping of a template literal containing a negated placeholder. +type AllCombined = { + [idx: Uppercase<`foo${string & not "bar"}`>]: number; +}; + +declare let allCombined: AllCombined; +allCombined["FOOBAZ"] = 1; // depends on representation +allCombined["foobaz"] = 1; // depends on representation +allCombined["FOOBAR"] = 1; // depends on representation + +// Index signature whose key is a template literal whose placeholder is a string mapping of a negated type. +type AllCombined2 = { + [idx: `foo${Uppercase}`]: number; +}; + +declare let allCombined2: AllCombined2; +allCombined2["fooBAZ"] = 1; // depends on representation +allCombined2["foobaz"] = 1; // depends on representation + +// Mapped type form combining all three. +type MappedAll = { + [k in Uppercase<`foo${string & not "bar"}`>]: number; +}; + +// Generic composition of all three. +type WrapAll = { + [idx: Uppercase<`foo${T & not "bar"}`>]: number; +}; +type WrapAllString = WrapAll; +type WrapAllLiteral = WrapAll<"baz">; diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInStringMapping.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInStringMapping.ts new file mode 100644 index 0000000000000..6516891c033b4 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInStringMapping.ts @@ -0,0 +1,34 @@ +// @strict: true +// @noEmit: true + +// Negated types used with intrinsic string mapping types. + +// Uppercase applied to a negated type: `Uppercase`. +type U1 = Uppercase; +type U2 = Uppercase; +type U3 = Uppercase; +type U4 = Uppercase; + +// Negation applied to a string mapping type: `not Uppercase`. +type N1 = not Uppercase<"bar">; +type N2 = not Uppercase; +type N3 = not Lowercase<"ABC">; + +// Generic forms. +type MapUpper = Uppercase; +type MapUpperString = MapUpper; +type MapUpperLiteral = MapUpper<"baz">; + +type NegUpper = not Uppercase; +type NegUpperString = NegUpper; +type NegUpperLiteral = NegUpper<"baz">; + +// Assignability probes. +declare let u1: U1; +declare let n1: N1; + +u1 = "BAZ"; // depends on representation +u1 = "baz"; // depends on representation + +n1 = "baz"; // depends on representation +n1 = "BAR"; // depends on representation diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInStringMappingAndIndexSignatures.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInStringMappingAndIndexSignatures.ts new file mode 100644 index 0000000000000..44df48da186f1 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesInStringMappingAndIndexSignatures.ts @@ -0,0 +1,34 @@ +// @strict: true +// @noEmit: true + +// Combination: negated types with BOTH string mapping types and index signatures. + +// Index signature whose key is a string mapping of a negated type. +type UpperKey = { + [idx: Uppercase]: number; +}; + +declare let upperKey: UpperKey; +upperKey["FOO"] = 1; // depends on representation +upperKey["foo"] = 1; // depends on representation + +// Index signature whose key is a negation of a string mapping type. +type NotUpperKey = { + [idx: string & not Uppercase]: number; +}; + +declare let notUpperKey: NotUpperKey; +notUpperKey["foo"] = 1; // depends on representation +notUpperKey["FOO"] = 1; // depends on representation + +// Mapped type over a string-mapping key type that uses a negated placeholder. +type MappedUpper = { + [k in Uppercase]: number; +}; + +// Generic index signature combination. +type WrapUpperKey = { + [idx: Uppercase]: number; +}; +type WrapUpperKeyString = WrapUpperKey; +type WrapUpperKeyLiteral = WrapUpperKey<"baz">; diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesNormalizationIdentities.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesNormalizationIdentities.ts new file mode 100644 index 0000000000000..3e7e681f29f9d --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesNormalizationIdentities.ts @@ -0,0 +1,42 @@ +// @strict: true +// @noEmit: true + +// Normalization / identity rules for the `not` type operator. + +// not any => any +type NotAny = not any; + +// not unknown => never +type NotUnknown = not unknown; + +// not never => unknown +type NotNever = not never; + +// Negated nullish / void. +type NotVoid = not void; +type NotNull = not null; +type NotUndefined = not undefined; + +// Double negation collapses: not not T => T. +type DoubleNegString = not not string; +type DoubleNegLiteral = not not "a"; +type TripleNegString = not not not string; // => not string + +// Double negation on a generic type parameter. +type DoubleNeg = not not T; +type DoubleNegApplied = DoubleNeg; + +// Assignability probes confirming the identities. +declare let notNever: NotNever; // unknown +declare let anyVal: any; +declare let str: string; + +notNever = str; // ok (unknown accepts anything) +anyVal = notNever; // ok + +declare let notUnknown: NotUnknown; // never +notUnknown = str; // error (nothing is assignable to never) + +declare let dnStr: DoubleNegString; // string +dnStr = "hello"; // ok +dnStr = 0; // error diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesSatisfiesAndArrays.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesSatisfiesAndArrays.ts new file mode 100644 index 0000000000000..0a5b8ebdc29cc --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesSatisfiesAndArrays.ts @@ -0,0 +1,37 @@ +// @strict: true +// @noEmit: true + +// Negated types with the `satisfies` operator and with array/tuple element types. + +// satisfies against a negated type. +declare const n: number; +const s1 = n satisfies not string; // should be ok (number is not a string) + +declare const str: string; +const s2 = str satisfies not string; // should error (string is a string) + +const s3 = 42 satisfies not "reserved"; // ok +const s4 = "reserved" satisfies not "reserved"; // should error + +// Array of a negated element type. +type NotStringArray = (not string)[]; +declare let arr: NotStringArray; +arr = [1, 2, 3]; // ok +arr = [{}, true, 0]; // ok: a fresh `{}` literal is treated as a closed empty object, disjoint from `string` +arr = ["a"]; // should error (element is a string) +arr = [1, "a"]; // should error (one element is a string) + +// Tuple with a negated element type. +type Pair = [not string, string]; +declare let pair: Pair; +pair = [1, "ok"]; // ok +pair = ["no", "ok"]; // should error (first element is a string) + +// Readonly array of negated element type, element access. +declare const ra: readonly (not number)[]; +const elem = ra[0]; // element type probe + +// Spread / iteration of a negated element array. +function sum(...args: (not string)[]) {} +sum(1, 2, {}); // ok: a fresh `{}` literal is treated as a closed empty object, disjoint from `string` +sum(1, "x"); // should error diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesSimplifyInIntersections.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesSimplifyInIntersections.ts new file mode 100644 index 0000000000000..b2ba97c84a63f --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesSimplifyInIntersections.ts @@ -0,0 +1,2 @@ +type A = boolean & not true; // false +type B = "w" & not string; // never diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesTruthinessFacts.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesTruthinessFacts.ts new file mode 100644 index 0000000000000..4de7cac7a9598 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedTypesTruthinessFacts.ts @@ -0,0 +1,50 @@ +// @strict: true +// @noEmit: true + +// Type facts for negated types drive control-flow narrowing. An intersection of negated +// falsy values excludes every falsy value, so a truthiness guard on such a type makes the +// falsy branch unreachable (never). This relies on the per-falsy-value "could be" facts, +// which getIntersectionTypeFacts AND-combines and then uses to clear a spurious Falsy fact. + +// A fully-truthy type: excludes every falsy value ("", 0, 0n, null, undefined, false). +type Truthy = not "" & not 0 & not 0n & not null & not undefined & not false; + +declare const t: Truthy; +if (t) { + t; // Truthy +} else { + t; // never +} + +// `string & not ""` is exactly the non-empty strings: truthy, and the falsy branch is unreachable. +declare const s: string & not ""; +if (s) { + s; // string & not "" +} else { + s; // never +} + +// `number & not 0` is truthy (only falsy number is 0, ignoring NaN like the checker does). +declare const n: number & not 0; +if (n) { + n; // number & not 0 +} else { + n; // never +} + +// A single negation still leaves the falsy branch reachable: `not null` can be 0/""/false/undefined. +declare const u: not null; +if (u) { + u; // not null +} else { + u; // not null (still falsy-capable, so not never) +} + +// Omitting `not 0n` leaves 0n as a reachable falsy value, so the falsy branch is not never. +type AlmostTruthy = not "" & not 0 & not null & not undefined & not false; +declare const a: AlmostTruthy; +if (a) { + a; // AlmostTruthy +} else { + a; // still falsy-capable via 0n, so not never +} diff --git a/tsc/testdata/tests/cases/conformance/types/negated/negatedUnionComplementSimplifies.ts b/tsc/testdata/tests/cases/conformance/types/negated/negatedUnionComplementSimplifies.ts new file mode 100644 index 0000000000000..5da31eb7b6f55 --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/types/negated/negatedUnionComplementSimplifies.ts @@ -0,0 +1,39 @@ +// @strict: true +// @noEmit: true + +// The union converse of the intersection complement simplification: a type unioned with its +// complement covers every value, so `T | not T` reduces to `unknown`. + +// Basic law of excluded middle. +type A = string | not string; +declare const a: A; +a; // unknown + +// A literal unioned with the negation of its base is also unknown, because the base covers the literal. +type B = string | not "w"; +declare const b: B; +b; // unknown + +// An object type and its complement. +interface Point { + x: number; + y: number; +} +type C = Point | not Point; +declare const c: C; +c; // unknown + +// Type parameter form. +function f(x: T | not T) { + x; // unknown +} + +// Not saturated: `"w" | not string` is NOT unknown, because `string` is not a subtype of `"w"`. +type D = "w" | not string; +declare const d: D; +d; // "w" | not string + +// Extra non-negated members still saturate when their union covers the negated base. +type E = "w" | string | not string; +declare const e: E; +e; // unknown