From 2fb109d193a360a699850916a241dfca1764f23f Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Thu, 17 Feb 2022 18:27:13 +0200 Subject: [PATCH 01/11] feat(7481): add explicit type compatibility check with 'satisfies' expression --- src/compiler/checker.ts | 18 + src/compiler/diagnosticMessages.json | 8 + src/compiler/emitter.ts | 12 + src/compiler/factory/nodeFactory.ts | 24 + src/compiler/factory/nodeTests.ts | 4 + src/compiler/factory/utilities.ts | 1 + src/compiler/parser.ts | 13 +- src/compiler/program.ts | 3 + src/compiler/scanner.ts | 1 + src/compiler/transformers/ts.ts | 8 + src/compiler/types.ts | 12 + src/compiler/utilities.ts | 8 +- src/compiler/utilitiesPublic.ts | 1 + src/compiler/visitorPublic.ts | 6 + src/harness/fourslashInterfaceImpl.ts | 4 + src/services/callHierarchy.ts | 4 + src/services/classifier.ts | 1 + src/services/completions.ts | 4 + src/services/formatting/rules.ts | 1 + .../reference/api/tsserverlibrary.d.ts | 446 +++++++++--------- tests/baselines/reference/api/typescript.d.ts | 446 +++++++++--------- .../completionsCommentsClass.baseline | 12 + .../completionsCommentsClassMembers.baseline | 240 ++++++++++ ...completionsCommentsCommentParsing.baseline | 84 ++++ ...etionsCommentsFunctionDeclaration.baseline | 36 ++ ...letionsCommentsFunctionExpression.baseline | 48 ++ ...FileCompilationTypeSatisfaction.errors.txt | 8 + .../jsFileCompilationTypeSatisfaction.js | 6 + .../jsFileCompilationTypeSatisfaction.symbols | 5 + .../jsFileCompilationTypeSatisfaction.types | 6 + .../reference/typeSatisfaction.errors.txt | 31 ++ tests/baselines/reference/typeSatisfaction.js | 25 + .../reference/typeSatisfaction.symbols | 48 ++ .../reference/typeSatisfaction.types | 57 +++ ...peSatisfactionWithDefaultExport.errors.txt | 20 + .../typeSatisfactionWithDefaultExport.js | 19 + .../typeSatisfactionWithDefaultExport.symbols | 21 + .../typeSatisfactionWithDefaultExport.types | 20 + .../jsFileCompilationTypeSatisfaction.ts | 5 + .../typeSatisfaction/typeSatisfaction.ts | 16 + .../typeSatisfactionWithDefaultExport.ts | 13 + .../fourslash/completionSatisfiesKeyword.ts | 11 + .../fourslash/satisfiesOperatorCompletion.ts | 7 + 43 files changed, 1324 insertions(+), 439 deletions(-) create mode 100644 tests/baselines/reference/jsFileCompilationTypeSatisfaction.errors.txt create mode 100644 tests/baselines/reference/jsFileCompilationTypeSatisfaction.js create mode 100644 tests/baselines/reference/jsFileCompilationTypeSatisfaction.symbols create mode 100644 tests/baselines/reference/jsFileCompilationTypeSatisfaction.types create mode 100644 tests/baselines/reference/typeSatisfaction.errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction.js create mode 100644 tests/baselines/reference/typeSatisfaction.symbols create mode 100644 tests/baselines/reference/typeSatisfaction.types create mode 100644 tests/baselines/reference/typeSatisfactionWithDefaultExport.errors.txt create mode 100644 tests/baselines/reference/typeSatisfactionWithDefaultExport.js create mode 100644 tests/baselines/reference/typeSatisfactionWithDefaultExport.symbols create mode 100644 tests/baselines/reference/typeSatisfactionWithDefaultExport.types create mode 100644 tests/cases/compiler/jsFileCompilationTypeSatisfaction.ts create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfactionWithDefaultExport.ts create mode 100644 tests/cases/fourslash/completionSatisfiesKeyword.ts create mode 100644 tests/cases/fourslash/satisfiesOperatorCompletion.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cbd86af7c4334..388b4c7d08c12 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26740,6 +26740,8 @@ namespace ts { } case SyntaxKind.NonNullExpression: return getContextualType(parent as NonNullExpression, contextFlags); + case SyntaxKind.SatisfiesExpression: + return getTypeFromTypeNode((parent as SatisfiesExpression).type); case SyntaxKind.JsxExpression: return getContextualTypeForJsxExpression(parent as JsxExpression); case SyntaxKind.JsxAttribute: @@ -31576,6 +31578,20 @@ namespace ts { } } + function checkSatisfiesExpression(node: SatisfiesExpression) { + checkSourceElement(node.type); + + const targetType = getTypeFromTypeNode(node.type); + if (isErrorType(targetType)) { + return targetType; + } + + const exprType = checkExpression(node.expression); + checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, node.type, node.expression, Diagnostics.Type_0_does_not_satisfy_the_expected_type_1); + + return exprType; + } + function checkMetaProperty(node: MetaProperty): Type { checkGrammarMetaProperty(node); @@ -34340,6 +34356,8 @@ namespace ts { return checkNonNullAssertion(node as NonNullExpression); case SyntaxKind.ExpressionWithTypeArguments: return checkExpressionWithTypeArguments(node as ExpressionWithTypeArguments); + case SyntaxKind.SatisfiesExpression: + return checkSatisfiesExpression(node as SatisfiesExpression); case SyntaxKind.MetaProperty: return checkMetaProperty(node as MetaProperty); case SyntaxKind.DeleteExpression: diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 0418b54a2ed80..74002763126f8 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1072,6 +1072,10 @@ "category": "Error", "code": 1359 }, + "Type '{0}' does not satisfy the expected type '{1}'.": { + "category": "Error", + "code": 1360 + }, "'{0}' cannot be used as a value because it was imported using 'import type'.": { "category": "Error", "code": 1361 @@ -6204,6 +6208,10 @@ "category": "Error", "code": 8034 }, + "Type satisfaction expressions can only be used in TypeScript files.": { + "category": "Error", + "code": 8035 + }, "Declaration emit for this file requires using private name '{0}'. An explicit type annotation may unblock declaration emit.": { "category": "Error", "code": 9005 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 9e5b39bd7a812..21322ca769c65 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1729,6 +1729,8 @@ namespace ts { return emitNonNullExpression(node as NonNullExpression); case SyntaxKind.ExpressionWithTypeArguments: return emitExpressionWithTypeArguments(node as ExpressionWithTypeArguments); + case SyntaxKind.SatisfiesExpression: + return emitSatisfiesExpression(node as SatisfiesExpression); case SyntaxKind.MetaProperty: return emitMetaProperty(node as MetaProperty); case SyntaxKind.SyntheticExpression: @@ -2807,6 +2809,16 @@ namespace ts { writeOperator("!"); } + function emitSatisfiesExpression(node: SatisfiesExpression) { + emitExpression(node.expression, /*parenthesizerRules*/ undefined); + if (node.type) { + writeSpace(); + writeKeyword("satisfies"); + writeSpace(); + emit(node.type); + } + } + function emitMetaProperty(node: MetaProperty) { writeToken(node.keywordToken, node.pos, writePunctuation); writePunctuation("."); diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index cbddf4fb32447..7df50a72af0d0 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -218,6 +218,8 @@ namespace ts { updateAsExpression, createNonNullExpression, updateNonNullExpression, + createSatisfiesExpression, + updateSatisfiesExpression, createNonNullChain, updateNonNullChain, createMetaProperty, @@ -3101,6 +3103,26 @@ namespace ts { : node; } + // @api + function createSatisfiesExpression(expression: Expression, type: TypeNode) { + const node = createBaseExpression(SyntaxKind.SatisfiesExpression); + node.expression = expression; + node.type = type; + node.transformFlags |= + propagateChildFlags(node.expression) | + propagateChildFlags(node.type) | + TransformFlags.ContainsTypeScript; + return node; + } + + // @api + function updateSatisfiesExpression(node: SatisfiesExpression, expression: Expression, type: TypeNode) { + return node.expression !== expression + || node.type !== type + ? update(createSatisfiesExpression(expression, type), node) + : node; + } + // @api function createNonNullChain(expression: Expression) { const node = createBaseExpression(SyntaxKind.NonNullExpression); @@ -5592,6 +5614,7 @@ namespace ts { case SyntaxKind.ParenthesizedExpression: return updateParenthesizedExpression(outerExpression, expression); case SyntaxKind.TypeAssertionExpression: return updateTypeAssertion(outerExpression, outerExpression.type, expression); case SyntaxKind.AsExpression: return updateAsExpression(outerExpression, expression, outerExpression.type); + case SyntaxKind.SatisfiesExpression: return updateSatisfiesExpression(outerExpression, expression, outerExpression.type); case SyntaxKind.NonNullExpression: return updateNonNullExpression(outerExpression, expression); case SyntaxKind.PartiallyEmittedExpression: return updatePartiallyEmittedExpression(outerExpression, expression); } @@ -6327,6 +6350,7 @@ namespace ts { case SyntaxKind.ArrayBindingPattern: return TransformFlags.BindingPatternExcludes; case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.SatisfiesExpression: case SyntaxKind.AsExpression: case SyntaxKind.PartiallyEmittedExpression: case SyntaxKind.ParenthesizedExpression: diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts index 274ade1886dfc..f9e3423ecbd22 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -433,6 +433,10 @@ namespace ts { return node.kind === SyntaxKind.AsExpression; } + export function isSatisfiesExpression(node: Node): node is SatisfiesExpression { + return node.kind === SyntaxKind.SatisfiesExpression; + } + export function isNonNullExpression(node: Node): node is NonNullExpression { return node.kind === SyntaxKind.NonNullExpression; } diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index 7daa31c522732..8645a2aae8d47 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -437,6 +437,7 @@ namespace ts { return (kinds & OuterExpressionKinds.Parentheses) !== 0; case SyntaxKind.TypeAssertionExpression: case SyntaxKind.AsExpression: + case SyntaxKind.SatisfiesExpression: return (kinds & OuterExpressionKinds.TypeAssertions) !== 0; case SyntaxKind.NonNullExpression: return (kinds & OuterExpressionKinds.NonNullAssertions) !== 0; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index cd7ed6285cb84..16fb744cc8be3 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -277,6 +277,9 @@ namespace ts { visitNode(cbNode, (node as AsExpression).type); case SyntaxKind.NonNullExpression: return visitNode(cbNode, (node as NonNullExpression).expression); + case SyntaxKind.SatisfiesExpression: + return visitNode(cbNode, (node as SatisfiesExpression).expression) || + visitNode(cbNode, (node as SatisfiesExpression).type); case SyntaxKind.MetaProperty: return visitNode(cbNode, (node as MetaProperty).name); case SyntaxKind.ConditionalExpression: @@ -4680,7 +4683,7 @@ namespace ts { break; } - if (token() === SyntaxKind.AsKeyword) { + if (token() === SyntaxKind.AsKeyword || token() === SyntaxKind.SatisfiesKeyword) { // Make sure we *do* perform ASI for constructs like this: // var x = foo // as (Bar) @@ -4690,8 +4693,10 @@ namespace ts { break; } else { + const keywordKind = token(); nextToken(); - leftOperand = makeAsExpression(leftOperand, parseType()); + leftOperand = keywordKind === SyntaxKind.SatisfiesKeyword ? makeSatisfiesExpression(leftOperand, parseType()) : + makeAsExpression(leftOperand, parseType()); } } else { @@ -4710,6 +4715,10 @@ namespace ts { return getBinaryOperatorPrecedence(token()) > 0; } + function makeSatisfiesExpression(left: Expression, right: TypeNode): SatisfiesExpression { + return finishNode(factory.createSatisfiesExpression(left, right), left.pos); + } + function makeBinaryExpression(left: Expression, operatorToken: BinaryOperatorToken, right: Expression, pos: number): BinaryExpression { return finishNode(factory.createBinaryExpression(left, operatorToken, right), pos); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 004986b55dbae..e0ba5ede4c9ee 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2285,6 +2285,9 @@ namespace ts { case SyntaxKind.AsExpression: diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); return "skip"; + case SyntaxKind.SatisfiesExpression: + diagnostics.push(createDiagnosticForNode((node as SatisfiesExpression).type, Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files)); + return "skip"; case SyntaxKind.TypeAssertionExpression: Debug.fail(); // Won't parse these in a JS file anyway, as they are interpreted as JSX. } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 6cac0cb1936d1..07cfe1cb0407f 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -135,6 +135,7 @@ namespace ts { require: SyntaxKind.RequireKeyword, global: SyntaxKind.GlobalKeyword, return: SyntaxKind.ReturnKeyword, + satisfies: SyntaxKind.SatisfiesKeyword, set: SyntaxKind.SetKeyword, static: SyntaxKind.StaticKeyword, string: SyntaxKind.StringKeyword, diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index f8cec499a8fd3..55ac764b70711 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -513,6 +513,9 @@ namespace ts { // TypeScript type assertions are removed, but their subtrees are preserved. return visitAssertionExpression(node as AssertionExpression); + case SyntaxKind.SatisfiesExpression: + return visitSatisfiesExpression(node as SatisfiesExpression); + case SyntaxKind.CallExpression: return visitCallExpression(node as CallExpression); @@ -2275,6 +2278,11 @@ namespace ts { return factory.createPartiallyEmittedExpression(expression, node); } + function visitSatisfiesExpression(node: SatisfiesExpression): Expression { + const expression = visitNode(node.expression, visitor, isExpression); + return factory.createPartiallyEmittedExpression(expression, node); + } + function visitCallExpression(node: CallExpression) { return factory.updateCallExpression( node, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 54936e787bc7a..021867dbb03e2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -180,6 +180,7 @@ namespace ts { RequireKeyword, NumberKeyword, ObjectKeyword, + SatisfiesKeyword, SetKeyword, StringKeyword, SymbolKeyword, @@ -273,6 +274,7 @@ namespace ts { NonNullExpression, MetaProperty, SyntheticExpression, + SatisfiesExpression, // Misc TemplateSpan, @@ -602,6 +604,7 @@ namespace ts { | SyntaxKind.OverrideKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword + | SyntaxKind.SatisfiesKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword @@ -2486,6 +2489,12 @@ namespace ts { readonly expression: UnaryExpression; } + export interface SatisfiesExpression extends Expression { + readonly kind: SyntaxKind.SatisfiesExpression; + readonly expression: Expression; + readonly type: TypeNode; + } + export type AssertionExpression = | TypeAssertion | AsExpression @@ -7049,6 +7058,7 @@ namespace ts { export type OuterExpression = | ParenthesizedExpression | TypeAssertion + | SatisfiesExpression | AsExpression | NonNullExpression | PartiallyEmittedExpression; @@ -7378,6 +7388,8 @@ namespace ts { updateNonNullChain(node: NonNullChain, expression: Expression): NonNullChain; createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty; updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty; + createSatisfiesExpression(expression: Expression, type: TypeNode): SatisfiesExpression; + updateSatisfiesExpression(node: SatisfiesExpression, expression: Expression, type: TypeNode): SatisfiesExpression; // // Misc diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 651b29d0dc9be..844aa0cf18aca 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1975,6 +1975,7 @@ namespace ts { case SyntaxKind.TaggedTemplateExpression: case SyntaxKind.AsExpression: case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.SatisfiesExpression: case SyntaxKind.NonNullExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.FunctionExpression: @@ -2073,6 +2074,8 @@ namespace ts { return (parent as ExpressionWithTypeArguments).expression === node && !isPartOfTypeNode(parent); case SyntaxKind.ShorthandPropertyAssignment: return (parent as ShorthandPropertyAssignment).objectAssignmentInitializer === node; + case SyntaxKind.SatisfiesExpression: + return node === (parent as SatisfiesExpression).expression; default: return isExpressionNode(parent); } @@ -3774,6 +3777,7 @@ namespace ts { return OperatorPrecedence.Member; case SyntaxKind.AsExpression: + case SyntaxKind.SatisfiesExpression: return OperatorPrecedence.Relational; case SyntaxKind.ThisKeyword: @@ -3832,6 +3836,7 @@ namespace ts { case SyntaxKind.InstanceOfKeyword: case SyntaxKind.InKeyword: case SyntaxKind.AsKeyword: + case SyntaxKind.SatisfiesKeyword: return OperatorPrecedence.Relational; case SyntaxKind.LessThanLessThanToken: case SyntaxKind.GreaterThanGreaterThanToken: @@ -5839,7 +5844,8 @@ namespace ts { case SyntaxKind.PropertyAccessExpression: case SyntaxKind.NonNullExpression: case SyntaxKind.PartiallyEmittedExpression: - node = (node as CallExpression | PropertyAccessExpression | ElementAccessExpression | AsExpression | NonNullExpression | PartiallyEmittedExpression).expression; + case SyntaxKind.SatisfiesExpression: + node = (node as CallExpression | PropertyAccessExpression | ElementAccessExpression | AsExpression | NonNullExpression | PartiallyEmittedExpression | SatisfiesExpression).expression; continue; } diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 4e1ff57f08be4..e9437ff55c3d2 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -1600,6 +1600,7 @@ namespace ts { case SyntaxKind.OmittedExpression: case SyntaxKind.CommaListExpression: case SyntaxKind.PartiallyEmittedExpression: + case SyntaxKind.SatisfiesExpression: return true; default: return isUnaryExpressionKind(kind); diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index 66840b760472c..355f8d4a7faa2 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -852,6 +852,12 @@ namespace ts { nodeVisitor(node.expression, visitor, isExpression), nodeVisitor(node.type, visitor, isTypeNode)); + case SyntaxKind.SatisfiesExpression: + Debug.type(node); + return factory.updateSatisfiesExpression(node, + nodeVisitor(node.expression, visitor, isExpression), + nodeVisitor(node.type, visitor, isTypeNode)); + case SyntaxKind.NonNullExpression: if (node.flags & NodeFlags.OptionalChain) { Debug.type(node); diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 98b61cf2fb55a..fdc5aa039bb20 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -1346,6 +1346,7 @@ namespace FourSlashInterface { "package", "readonly", "return", + "satisfies", "string", "super", "switch", @@ -1461,6 +1462,7 @@ namespace FourSlashInterface { "null", "package", "return", + "satisfies", "super", "switch", "this", @@ -1558,6 +1560,7 @@ namespace FourSlashInterface { "package", "readonly", "return", + "satisfies", "string", "super", "switch", @@ -1612,6 +1615,7 @@ namespace FourSlashInterface { "null", "package", "return", + "satisfies", "super", "switch", "this", diff --git a/src/services/callHierarchy.ts b/src/services/callHierarchy.ts index bfb533b0160b2..57f6d5af275e8 100644 --- a/src/services/callHierarchy.ts +++ b/src/services/callHierarchy.ts @@ -449,6 +449,10 @@ namespace ts.CallHierarchy { recordCallSite(node as AccessExpression); forEachChild(node, collect); break; + case SyntaxKind.SatisfiesExpression: + // do not descend into the type side of an assertion + collect((node as SatisfiesExpression).expression); + return; } if (isPartOfTypeNode(node)) { diff --git a/src/services/classifier.ts b/src/services/classifier.ts index ed8445b8f3987..9565903f556bb 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -369,6 +369,7 @@ namespace ts { case SyntaxKind.InstanceOfKeyword: case SyntaxKind.InKeyword: case SyntaxKind.AsKeyword: + case SyntaxKind.SatisfiesKeyword: case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: diff --git a/src/services/completions.ts b/src/services/completions.ts index ca10ba189b5a6..a48de6367b652 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -2471,6 +2471,9 @@ namespace ts.Completions { case SyntaxKind.ExtendsKeyword: return parentKind === SyntaxKind.TypeParameter; + + case SyntaxKind.SatisfiesKeyword: + return parentKind === SyntaxKind.SatisfiesExpression; } } return false; @@ -3650,6 +3653,7 @@ namespace ts.Completions { return kind === SyntaxKind.AsyncKeyword || kind === SyntaxKind.AwaitKeyword || kind === SyntaxKind.AsKeyword + || kind === SyntaxKind.SatisfiesKeyword || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind); } diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 76a0d34853153..974bc208fbd9e 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -449,6 +449,7 @@ namespace ts.formatting { case SyntaxKind.TypePredicate: case SyntaxKind.UnionType: case SyntaxKind.IntersectionType: + case SyntaxKind.SatisfiesExpression: return true; // equals in binding elements: function foo([[x, y] = [1, 2]]) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 255fb6a1305c7..5339d3b69bec3 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -253,212 +253,214 @@ declare namespace ts { RequireKeyword = 145, NumberKeyword = 146, ObjectKeyword = 147, - SetKeyword = 148, - StringKeyword = 149, - SymbolKeyword = 150, - TypeKeyword = 151, - UndefinedKeyword = 152, - UniqueKeyword = 153, - UnknownKeyword = 154, - FromKeyword = 155, - GlobalKeyword = 156, - BigIntKeyword = 157, - OverrideKeyword = 158, - OfKeyword = 159, - QualifiedName = 160, - ComputedPropertyName = 161, - TypeParameter = 162, - Parameter = 163, - Decorator = 164, - PropertySignature = 165, - PropertyDeclaration = 166, - MethodSignature = 167, - MethodDeclaration = 168, - ClassStaticBlockDeclaration = 169, - Constructor = 170, - GetAccessor = 171, - SetAccessor = 172, - CallSignature = 173, - ConstructSignature = 174, - IndexSignature = 175, - TypePredicate = 176, - TypeReference = 177, - FunctionType = 178, - ConstructorType = 179, - TypeQuery = 180, - TypeLiteral = 181, - ArrayType = 182, - TupleType = 183, - OptionalType = 184, - RestType = 185, - UnionType = 186, - IntersectionType = 187, - ConditionalType = 188, - InferType = 189, - ParenthesizedType = 190, - ThisType = 191, - TypeOperator = 192, - IndexedAccessType = 193, - MappedType = 194, - LiteralType = 195, - NamedTupleMember = 196, - TemplateLiteralType = 197, - TemplateLiteralTypeSpan = 198, - ImportType = 199, - ObjectBindingPattern = 200, - ArrayBindingPattern = 201, - BindingElement = 202, - ArrayLiteralExpression = 203, - ObjectLiteralExpression = 204, - PropertyAccessExpression = 205, - ElementAccessExpression = 206, - CallExpression = 207, - NewExpression = 208, - TaggedTemplateExpression = 209, - TypeAssertionExpression = 210, - ParenthesizedExpression = 211, - FunctionExpression = 212, - ArrowFunction = 213, - DeleteExpression = 214, - TypeOfExpression = 215, - VoidExpression = 216, - AwaitExpression = 217, - PrefixUnaryExpression = 218, - PostfixUnaryExpression = 219, - BinaryExpression = 220, - ConditionalExpression = 221, - TemplateExpression = 222, - YieldExpression = 223, - SpreadElement = 224, - ClassExpression = 225, - OmittedExpression = 226, - ExpressionWithTypeArguments = 227, - AsExpression = 228, - NonNullExpression = 229, - MetaProperty = 230, - SyntheticExpression = 231, - TemplateSpan = 232, - SemicolonClassElement = 233, - Block = 234, - EmptyStatement = 235, - VariableStatement = 236, - ExpressionStatement = 237, - IfStatement = 238, - DoStatement = 239, - WhileStatement = 240, - ForStatement = 241, - ForInStatement = 242, - ForOfStatement = 243, - ContinueStatement = 244, - BreakStatement = 245, - ReturnStatement = 246, - WithStatement = 247, - SwitchStatement = 248, - LabeledStatement = 249, - ThrowStatement = 250, - TryStatement = 251, - DebuggerStatement = 252, - VariableDeclaration = 253, - VariableDeclarationList = 254, - FunctionDeclaration = 255, - ClassDeclaration = 256, - InterfaceDeclaration = 257, - TypeAliasDeclaration = 258, - EnumDeclaration = 259, - ModuleDeclaration = 260, - ModuleBlock = 261, - CaseBlock = 262, - NamespaceExportDeclaration = 263, - ImportEqualsDeclaration = 264, - ImportDeclaration = 265, - ImportClause = 266, - NamespaceImport = 267, - NamedImports = 268, - ImportSpecifier = 269, - ExportAssignment = 270, - ExportDeclaration = 271, - NamedExports = 272, - NamespaceExport = 273, - ExportSpecifier = 274, - MissingDeclaration = 275, - ExternalModuleReference = 276, - JsxElement = 277, - JsxSelfClosingElement = 278, - JsxOpeningElement = 279, - JsxClosingElement = 280, - JsxFragment = 281, - JsxOpeningFragment = 282, - JsxClosingFragment = 283, - JsxAttribute = 284, - JsxAttributes = 285, - JsxSpreadAttribute = 286, - JsxExpression = 287, - CaseClause = 288, - DefaultClause = 289, - HeritageClause = 290, - CatchClause = 291, - AssertClause = 292, - AssertEntry = 293, - PropertyAssignment = 294, - ShorthandPropertyAssignment = 295, - SpreadAssignment = 296, - EnumMember = 297, - UnparsedPrologue = 298, - UnparsedPrepend = 299, - UnparsedText = 300, - UnparsedInternalText = 301, - UnparsedSyntheticReference = 302, - SourceFile = 303, - Bundle = 304, - UnparsedSource = 305, - InputFiles = 306, - JSDocTypeExpression = 307, - JSDocNameReference = 308, - JSDocMemberName = 309, - JSDocAllType = 310, - JSDocUnknownType = 311, - JSDocNullableType = 312, - JSDocNonNullableType = 313, - JSDocOptionalType = 314, - JSDocFunctionType = 315, - JSDocVariadicType = 316, - JSDocNamepathType = 317, - JSDocComment = 318, - JSDocText = 319, - JSDocTypeLiteral = 320, - JSDocSignature = 321, - JSDocLink = 322, - JSDocLinkCode = 323, - JSDocLinkPlain = 324, - JSDocTag = 325, - JSDocAugmentsTag = 326, - JSDocImplementsTag = 327, - JSDocAuthorTag = 328, - JSDocDeprecatedTag = 329, - JSDocClassTag = 330, - JSDocPublicTag = 331, - JSDocPrivateTag = 332, - JSDocProtectedTag = 333, - JSDocReadonlyTag = 334, - JSDocOverrideTag = 335, - JSDocCallbackTag = 336, - JSDocEnumTag = 337, - JSDocParameterTag = 338, - JSDocReturnTag = 339, - JSDocThisTag = 340, - JSDocTypeTag = 341, - JSDocTemplateTag = 342, - JSDocTypedefTag = 343, - JSDocSeeTag = 344, - JSDocPropertyTag = 345, - SyntaxList = 346, - NotEmittedStatement = 347, - PartiallyEmittedExpression = 348, - CommaListExpression = 349, - MergeDeclarationMarker = 350, - EndOfDeclarationMarker = 351, - SyntheticReferenceExpression = 352, - Count = 353, + SatisfiesKeyword = 148, + SetKeyword = 149, + StringKeyword = 150, + SymbolKeyword = 151, + TypeKeyword = 152, + UndefinedKeyword = 153, + UniqueKeyword = 154, + UnknownKeyword = 155, + FromKeyword = 156, + GlobalKeyword = 157, + BigIntKeyword = 158, + OverrideKeyword = 159, + OfKeyword = 160, + QualifiedName = 161, + ComputedPropertyName = 162, + TypeParameter = 163, + Parameter = 164, + Decorator = 165, + PropertySignature = 166, + PropertyDeclaration = 167, + MethodSignature = 168, + MethodDeclaration = 169, + ClassStaticBlockDeclaration = 170, + Constructor = 171, + GetAccessor = 172, + SetAccessor = 173, + CallSignature = 174, + ConstructSignature = 175, + IndexSignature = 176, + TypePredicate = 177, + TypeReference = 178, + FunctionType = 179, + ConstructorType = 180, + TypeQuery = 181, + TypeLiteral = 182, + ArrayType = 183, + TupleType = 184, + OptionalType = 185, + RestType = 186, + UnionType = 187, + IntersectionType = 188, + ConditionalType = 189, + InferType = 190, + ParenthesizedType = 191, + ThisType = 192, + TypeOperator = 193, + IndexedAccessType = 194, + MappedType = 195, + LiteralType = 196, + NamedTupleMember = 197, + TemplateLiteralType = 198, + TemplateLiteralTypeSpan = 199, + ImportType = 200, + ObjectBindingPattern = 201, + ArrayBindingPattern = 202, + BindingElement = 203, + ArrayLiteralExpression = 204, + ObjectLiteralExpression = 205, + PropertyAccessExpression = 206, + ElementAccessExpression = 207, + CallExpression = 208, + NewExpression = 209, + TaggedTemplateExpression = 210, + TypeAssertionExpression = 211, + ParenthesizedExpression = 212, + FunctionExpression = 213, + ArrowFunction = 214, + DeleteExpression = 215, + TypeOfExpression = 216, + VoidExpression = 217, + AwaitExpression = 218, + PrefixUnaryExpression = 219, + PostfixUnaryExpression = 220, + BinaryExpression = 221, + ConditionalExpression = 222, + TemplateExpression = 223, + YieldExpression = 224, + SpreadElement = 225, + ClassExpression = 226, + OmittedExpression = 227, + ExpressionWithTypeArguments = 228, + AsExpression = 229, + NonNullExpression = 230, + MetaProperty = 231, + SyntheticExpression = 232, + SatisfiesExpression = 233, + TemplateSpan = 234, + SemicolonClassElement = 235, + Block = 236, + EmptyStatement = 237, + VariableStatement = 238, + ExpressionStatement = 239, + IfStatement = 240, + DoStatement = 241, + WhileStatement = 242, + ForStatement = 243, + ForInStatement = 244, + ForOfStatement = 245, + ContinueStatement = 246, + BreakStatement = 247, + ReturnStatement = 248, + WithStatement = 249, + SwitchStatement = 250, + LabeledStatement = 251, + ThrowStatement = 252, + TryStatement = 253, + DebuggerStatement = 254, + VariableDeclaration = 255, + VariableDeclarationList = 256, + FunctionDeclaration = 257, + ClassDeclaration = 258, + InterfaceDeclaration = 259, + TypeAliasDeclaration = 260, + EnumDeclaration = 261, + ModuleDeclaration = 262, + ModuleBlock = 263, + CaseBlock = 264, + NamespaceExportDeclaration = 265, + ImportEqualsDeclaration = 266, + ImportDeclaration = 267, + ImportClause = 268, + NamespaceImport = 269, + NamedImports = 270, + ImportSpecifier = 271, + ExportAssignment = 272, + ExportDeclaration = 273, + NamedExports = 274, + NamespaceExport = 275, + ExportSpecifier = 276, + MissingDeclaration = 277, + ExternalModuleReference = 278, + JsxElement = 279, + JsxSelfClosingElement = 280, + JsxOpeningElement = 281, + JsxClosingElement = 282, + JsxFragment = 283, + JsxOpeningFragment = 284, + JsxClosingFragment = 285, + JsxAttribute = 286, + JsxAttributes = 287, + JsxSpreadAttribute = 288, + JsxExpression = 289, + CaseClause = 290, + DefaultClause = 291, + HeritageClause = 292, + CatchClause = 293, + AssertClause = 294, + AssertEntry = 295, + PropertyAssignment = 296, + ShorthandPropertyAssignment = 297, + SpreadAssignment = 298, + EnumMember = 299, + UnparsedPrologue = 300, + UnparsedPrepend = 301, + UnparsedText = 302, + UnparsedInternalText = 303, + UnparsedSyntheticReference = 304, + SourceFile = 305, + Bundle = 306, + UnparsedSource = 307, + InputFiles = 308, + JSDocTypeExpression = 309, + JSDocNameReference = 310, + JSDocMemberName = 311, + JSDocAllType = 312, + JSDocUnknownType = 313, + JSDocNullableType = 314, + JSDocNonNullableType = 315, + JSDocOptionalType = 316, + JSDocFunctionType = 317, + JSDocVariadicType = 318, + JSDocNamepathType = 319, + JSDocComment = 320, + JSDocText = 321, + JSDocTypeLiteral = 322, + JSDocSignature = 323, + JSDocLink = 324, + JSDocLinkCode = 325, + JSDocLinkPlain = 326, + JSDocTag = 327, + JSDocAugmentsTag = 328, + JSDocImplementsTag = 329, + JSDocAuthorTag = 330, + JSDocDeprecatedTag = 331, + JSDocClassTag = 332, + JSDocPublicTag = 333, + JSDocPrivateTag = 334, + JSDocProtectedTag = 335, + JSDocReadonlyTag = 336, + JSDocOverrideTag = 337, + JSDocCallbackTag = 338, + JSDocEnumTag = 339, + JSDocParameterTag = 340, + JSDocReturnTag = 341, + JSDocThisTag = 342, + JSDocTypeTag = 343, + JSDocTemplateTag = 344, + JSDocTypedefTag = 345, + JSDocSeeTag = 346, + JSDocPropertyTag = 347, + SyntaxList = 348, + NotEmittedStatement = 349, + PartiallyEmittedExpression = 350, + CommaListExpression = 351, + MergeDeclarationMarker = 352, + EndOfDeclarationMarker = 353, + SyntheticReferenceExpression = 354, + Count = 355, FirstAssignment = 63, LastAssignment = 78, FirstCompoundAssignment = 64, @@ -466,15 +468,15 @@ declare namespace ts { FirstReservedWord = 81, LastReservedWord = 116, FirstKeyword = 81, - LastKeyword = 159, + LastKeyword = 160, FirstFutureReservedWord = 117, LastFutureReservedWord = 125, - FirstTypeNode = 176, - LastTypeNode = 199, + FirstTypeNode = 177, + LastTypeNode = 200, FirstPunctuation = 18, LastPunctuation = 78, FirstToken = 0, - LastToken = 159, + LastToken = 160, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -483,19 +485,19 @@ declare namespace ts { LastTemplateToken = 17, FirstBinaryOperator = 29, LastBinaryOperator = 78, - FirstStatement = 236, - LastStatement = 252, - FirstNode = 160, - FirstJSDocNode = 307, - LastJSDocNode = 345, - FirstJSDocTagNode = 325, - LastJSDocTagNode = 345, + FirstStatement = 238, + LastStatement = 254, + FirstNode = 161, + FirstJSDocNode = 309, + LastJSDocNode = 347, + FirstJSDocTagNode = 327, + LastJSDocTagNode = 347, } export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; export type PseudoLiteralSyntaxKind = SyntaxKind.TemplateHead | SyntaxKind.TemplateMiddle | SyntaxKind.TemplateTail; export type PunctuationSyntaxKind = SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.OpenParenToken | SyntaxKind.CloseParenToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.DotToken | SyntaxKind.DotDotDotToken | SyntaxKind.SemicolonToken | SyntaxKind.CommaToken | SyntaxKind.QuestionDotToken | SyntaxKind.LessThanToken | SyntaxKind.LessThanSlashToken | SyntaxKind.GreaterThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.EqualsEqualsToken | SyntaxKind.ExclamationEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.EqualsGreaterThanToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.AsteriskToken | SyntaxKind.AsteriskAsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken | SyntaxKind.PlusPlusToken | SyntaxKind.MinusMinusToken | SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken | SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken | SyntaxKind.ExclamationToken | SyntaxKind.TildeToken | SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken | SyntaxKind.QuestionToken | SyntaxKind.ColonToken | SyntaxKind.AtToken | SyntaxKind.BacktickToken | SyntaxKind.HashToken | SyntaxKind.EqualsToken | SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken; - export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.AssertKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InferKeyword | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IntrinsicKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.OfKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.OverrideKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; + export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.AssertKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InferKeyword | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IntrinsicKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.OfKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.OverrideKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SatisfiesKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; export type ModifierSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.ConstKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.ExportKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.OverrideKeyword | SyntaxKind.StaticKeyword; export type KeywordTypeSyntaxKind = SyntaxKind.AnyKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.IntrinsicKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VoidKeyword; export type TokenSyntaxKind = SyntaxKind.Unknown | SyntaxKind.EndOfFileToken | TriviaSyntaxKind | LiteralSyntaxKind | PseudoLiteralSyntaxKind | PunctuationSyntaxKind | SyntaxKind.Identifier | KeywordSyntaxKind; @@ -1312,6 +1314,11 @@ declare namespace ts { readonly type: TypeNode; readonly expression: UnaryExpression; } + export interface SatisfiesExpression extends Expression { + readonly kind: SyntaxKind.SatisfiesExpression; + readonly expression: Expression; + readonly type: TypeNode; + } export type AssertionExpression = TypeAssertion | AsExpression; export interface NonNullExpression extends LeftHandSideExpression { readonly kind: SyntaxKind.NonNullExpression; @@ -3512,6 +3519,8 @@ declare namespace ts { updateNonNullChain(node: NonNullChain, expression: Expression): NonNullChain; createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty; updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty; + createSatisfiesExpression(expression: Expression, type: TypeNode): SatisfiesExpression; + updateSatisfiesExpression(node: SatisfiesExpression, expression: Expression, type: TypeNode): SatisfiesExpression; createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; createSemicolonClassElement(): SemicolonClassElement; @@ -4623,6 +4632,7 @@ declare namespace ts { function isOmittedExpression(node: Node): node is OmittedExpression; function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments; function isAsExpression(node: Node): node is AsExpression; + function isSatisfiesExpression(node: Node): node is SatisfiesExpression; function isNonNullExpression(node: Node): node is NonNullExpression; function isMetaProperty(node: Node): node is MetaProperty; function isSyntheticExpression(node: Node): node is SyntheticExpression; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 63a6a9bc49be3..2d529e670c2a4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -253,212 +253,214 @@ declare namespace ts { RequireKeyword = 145, NumberKeyword = 146, ObjectKeyword = 147, - SetKeyword = 148, - StringKeyword = 149, - SymbolKeyword = 150, - TypeKeyword = 151, - UndefinedKeyword = 152, - UniqueKeyword = 153, - UnknownKeyword = 154, - FromKeyword = 155, - GlobalKeyword = 156, - BigIntKeyword = 157, - OverrideKeyword = 158, - OfKeyword = 159, - QualifiedName = 160, - ComputedPropertyName = 161, - TypeParameter = 162, - Parameter = 163, - Decorator = 164, - PropertySignature = 165, - PropertyDeclaration = 166, - MethodSignature = 167, - MethodDeclaration = 168, - ClassStaticBlockDeclaration = 169, - Constructor = 170, - GetAccessor = 171, - SetAccessor = 172, - CallSignature = 173, - ConstructSignature = 174, - IndexSignature = 175, - TypePredicate = 176, - TypeReference = 177, - FunctionType = 178, - ConstructorType = 179, - TypeQuery = 180, - TypeLiteral = 181, - ArrayType = 182, - TupleType = 183, - OptionalType = 184, - RestType = 185, - UnionType = 186, - IntersectionType = 187, - ConditionalType = 188, - InferType = 189, - ParenthesizedType = 190, - ThisType = 191, - TypeOperator = 192, - IndexedAccessType = 193, - MappedType = 194, - LiteralType = 195, - NamedTupleMember = 196, - TemplateLiteralType = 197, - TemplateLiteralTypeSpan = 198, - ImportType = 199, - ObjectBindingPattern = 200, - ArrayBindingPattern = 201, - BindingElement = 202, - ArrayLiteralExpression = 203, - ObjectLiteralExpression = 204, - PropertyAccessExpression = 205, - ElementAccessExpression = 206, - CallExpression = 207, - NewExpression = 208, - TaggedTemplateExpression = 209, - TypeAssertionExpression = 210, - ParenthesizedExpression = 211, - FunctionExpression = 212, - ArrowFunction = 213, - DeleteExpression = 214, - TypeOfExpression = 215, - VoidExpression = 216, - AwaitExpression = 217, - PrefixUnaryExpression = 218, - PostfixUnaryExpression = 219, - BinaryExpression = 220, - ConditionalExpression = 221, - TemplateExpression = 222, - YieldExpression = 223, - SpreadElement = 224, - ClassExpression = 225, - OmittedExpression = 226, - ExpressionWithTypeArguments = 227, - AsExpression = 228, - NonNullExpression = 229, - MetaProperty = 230, - SyntheticExpression = 231, - TemplateSpan = 232, - SemicolonClassElement = 233, - Block = 234, - EmptyStatement = 235, - VariableStatement = 236, - ExpressionStatement = 237, - IfStatement = 238, - DoStatement = 239, - WhileStatement = 240, - ForStatement = 241, - ForInStatement = 242, - ForOfStatement = 243, - ContinueStatement = 244, - BreakStatement = 245, - ReturnStatement = 246, - WithStatement = 247, - SwitchStatement = 248, - LabeledStatement = 249, - ThrowStatement = 250, - TryStatement = 251, - DebuggerStatement = 252, - VariableDeclaration = 253, - VariableDeclarationList = 254, - FunctionDeclaration = 255, - ClassDeclaration = 256, - InterfaceDeclaration = 257, - TypeAliasDeclaration = 258, - EnumDeclaration = 259, - ModuleDeclaration = 260, - ModuleBlock = 261, - CaseBlock = 262, - NamespaceExportDeclaration = 263, - ImportEqualsDeclaration = 264, - ImportDeclaration = 265, - ImportClause = 266, - NamespaceImport = 267, - NamedImports = 268, - ImportSpecifier = 269, - ExportAssignment = 270, - ExportDeclaration = 271, - NamedExports = 272, - NamespaceExport = 273, - ExportSpecifier = 274, - MissingDeclaration = 275, - ExternalModuleReference = 276, - JsxElement = 277, - JsxSelfClosingElement = 278, - JsxOpeningElement = 279, - JsxClosingElement = 280, - JsxFragment = 281, - JsxOpeningFragment = 282, - JsxClosingFragment = 283, - JsxAttribute = 284, - JsxAttributes = 285, - JsxSpreadAttribute = 286, - JsxExpression = 287, - CaseClause = 288, - DefaultClause = 289, - HeritageClause = 290, - CatchClause = 291, - AssertClause = 292, - AssertEntry = 293, - PropertyAssignment = 294, - ShorthandPropertyAssignment = 295, - SpreadAssignment = 296, - EnumMember = 297, - UnparsedPrologue = 298, - UnparsedPrepend = 299, - UnparsedText = 300, - UnparsedInternalText = 301, - UnparsedSyntheticReference = 302, - SourceFile = 303, - Bundle = 304, - UnparsedSource = 305, - InputFiles = 306, - JSDocTypeExpression = 307, - JSDocNameReference = 308, - JSDocMemberName = 309, - JSDocAllType = 310, - JSDocUnknownType = 311, - JSDocNullableType = 312, - JSDocNonNullableType = 313, - JSDocOptionalType = 314, - JSDocFunctionType = 315, - JSDocVariadicType = 316, - JSDocNamepathType = 317, - JSDocComment = 318, - JSDocText = 319, - JSDocTypeLiteral = 320, - JSDocSignature = 321, - JSDocLink = 322, - JSDocLinkCode = 323, - JSDocLinkPlain = 324, - JSDocTag = 325, - JSDocAugmentsTag = 326, - JSDocImplementsTag = 327, - JSDocAuthorTag = 328, - JSDocDeprecatedTag = 329, - JSDocClassTag = 330, - JSDocPublicTag = 331, - JSDocPrivateTag = 332, - JSDocProtectedTag = 333, - JSDocReadonlyTag = 334, - JSDocOverrideTag = 335, - JSDocCallbackTag = 336, - JSDocEnumTag = 337, - JSDocParameterTag = 338, - JSDocReturnTag = 339, - JSDocThisTag = 340, - JSDocTypeTag = 341, - JSDocTemplateTag = 342, - JSDocTypedefTag = 343, - JSDocSeeTag = 344, - JSDocPropertyTag = 345, - SyntaxList = 346, - NotEmittedStatement = 347, - PartiallyEmittedExpression = 348, - CommaListExpression = 349, - MergeDeclarationMarker = 350, - EndOfDeclarationMarker = 351, - SyntheticReferenceExpression = 352, - Count = 353, + SatisfiesKeyword = 148, + SetKeyword = 149, + StringKeyword = 150, + SymbolKeyword = 151, + TypeKeyword = 152, + UndefinedKeyword = 153, + UniqueKeyword = 154, + UnknownKeyword = 155, + FromKeyword = 156, + GlobalKeyword = 157, + BigIntKeyword = 158, + OverrideKeyword = 159, + OfKeyword = 160, + QualifiedName = 161, + ComputedPropertyName = 162, + TypeParameter = 163, + Parameter = 164, + Decorator = 165, + PropertySignature = 166, + PropertyDeclaration = 167, + MethodSignature = 168, + MethodDeclaration = 169, + ClassStaticBlockDeclaration = 170, + Constructor = 171, + GetAccessor = 172, + SetAccessor = 173, + CallSignature = 174, + ConstructSignature = 175, + IndexSignature = 176, + TypePredicate = 177, + TypeReference = 178, + FunctionType = 179, + ConstructorType = 180, + TypeQuery = 181, + TypeLiteral = 182, + ArrayType = 183, + TupleType = 184, + OptionalType = 185, + RestType = 186, + UnionType = 187, + IntersectionType = 188, + ConditionalType = 189, + InferType = 190, + ParenthesizedType = 191, + ThisType = 192, + TypeOperator = 193, + IndexedAccessType = 194, + MappedType = 195, + LiteralType = 196, + NamedTupleMember = 197, + TemplateLiteralType = 198, + TemplateLiteralTypeSpan = 199, + ImportType = 200, + ObjectBindingPattern = 201, + ArrayBindingPattern = 202, + BindingElement = 203, + ArrayLiteralExpression = 204, + ObjectLiteralExpression = 205, + PropertyAccessExpression = 206, + ElementAccessExpression = 207, + CallExpression = 208, + NewExpression = 209, + TaggedTemplateExpression = 210, + TypeAssertionExpression = 211, + ParenthesizedExpression = 212, + FunctionExpression = 213, + ArrowFunction = 214, + DeleteExpression = 215, + TypeOfExpression = 216, + VoidExpression = 217, + AwaitExpression = 218, + PrefixUnaryExpression = 219, + PostfixUnaryExpression = 220, + BinaryExpression = 221, + ConditionalExpression = 222, + TemplateExpression = 223, + YieldExpression = 224, + SpreadElement = 225, + ClassExpression = 226, + OmittedExpression = 227, + ExpressionWithTypeArguments = 228, + AsExpression = 229, + NonNullExpression = 230, + MetaProperty = 231, + SyntheticExpression = 232, + SatisfiesExpression = 233, + TemplateSpan = 234, + SemicolonClassElement = 235, + Block = 236, + EmptyStatement = 237, + VariableStatement = 238, + ExpressionStatement = 239, + IfStatement = 240, + DoStatement = 241, + WhileStatement = 242, + ForStatement = 243, + ForInStatement = 244, + ForOfStatement = 245, + ContinueStatement = 246, + BreakStatement = 247, + ReturnStatement = 248, + WithStatement = 249, + SwitchStatement = 250, + LabeledStatement = 251, + ThrowStatement = 252, + TryStatement = 253, + DebuggerStatement = 254, + VariableDeclaration = 255, + VariableDeclarationList = 256, + FunctionDeclaration = 257, + ClassDeclaration = 258, + InterfaceDeclaration = 259, + TypeAliasDeclaration = 260, + EnumDeclaration = 261, + ModuleDeclaration = 262, + ModuleBlock = 263, + CaseBlock = 264, + NamespaceExportDeclaration = 265, + ImportEqualsDeclaration = 266, + ImportDeclaration = 267, + ImportClause = 268, + NamespaceImport = 269, + NamedImports = 270, + ImportSpecifier = 271, + ExportAssignment = 272, + ExportDeclaration = 273, + NamedExports = 274, + NamespaceExport = 275, + ExportSpecifier = 276, + MissingDeclaration = 277, + ExternalModuleReference = 278, + JsxElement = 279, + JsxSelfClosingElement = 280, + JsxOpeningElement = 281, + JsxClosingElement = 282, + JsxFragment = 283, + JsxOpeningFragment = 284, + JsxClosingFragment = 285, + JsxAttribute = 286, + JsxAttributes = 287, + JsxSpreadAttribute = 288, + JsxExpression = 289, + CaseClause = 290, + DefaultClause = 291, + HeritageClause = 292, + CatchClause = 293, + AssertClause = 294, + AssertEntry = 295, + PropertyAssignment = 296, + ShorthandPropertyAssignment = 297, + SpreadAssignment = 298, + EnumMember = 299, + UnparsedPrologue = 300, + UnparsedPrepend = 301, + UnparsedText = 302, + UnparsedInternalText = 303, + UnparsedSyntheticReference = 304, + SourceFile = 305, + Bundle = 306, + UnparsedSource = 307, + InputFiles = 308, + JSDocTypeExpression = 309, + JSDocNameReference = 310, + JSDocMemberName = 311, + JSDocAllType = 312, + JSDocUnknownType = 313, + JSDocNullableType = 314, + JSDocNonNullableType = 315, + JSDocOptionalType = 316, + JSDocFunctionType = 317, + JSDocVariadicType = 318, + JSDocNamepathType = 319, + JSDocComment = 320, + JSDocText = 321, + JSDocTypeLiteral = 322, + JSDocSignature = 323, + JSDocLink = 324, + JSDocLinkCode = 325, + JSDocLinkPlain = 326, + JSDocTag = 327, + JSDocAugmentsTag = 328, + JSDocImplementsTag = 329, + JSDocAuthorTag = 330, + JSDocDeprecatedTag = 331, + JSDocClassTag = 332, + JSDocPublicTag = 333, + JSDocPrivateTag = 334, + JSDocProtectedTag = 335, + JSDocReadonlyTag = 336, + JSDocOverrideTag = 337, + JSDocCallbackTag = 338, + JSDocEnumTag = 339, + JSDocParameterTag = 340, + JSDocReturnTag = 341, + JSDocThisTag = 342, + JSDocTypeTag = 343, + JSDocTemplateTag = 344, + JSDocTypedefTag = 345, + JSDocSeeTag = 346, + JSDocPropertyTag = 347, + SyntaxList = 348, + NotEmittedStatement = 349, + PartiallyEmittedExpression = 350, + CommaListExpression = 351, + MergeDeclarationMarker = 352, + EndOfDeclarationMarker = 353, + SyntheticReferenceExpression = 354, + Count = 355, FirstAssignment = 63, LastAssignment = 78, FirstCompoundAssignment = 64, @@ -466,15 +468,15 @@ declare namespace ts { FirstReservedWord = 81, LastReservedWord = 116, FirstKeyword = 81, - LastKeyword = 159, + LastKeyword = 160, FirstFutureReservedWord = 117, LastFutureReservedWord = 125, - FirstTypeNode = 176, - LastTypeNode = 199, + FirstTypeNode = 177, + LastTypeNode = 200, FirstPunctuation = 18, LastPunctuation = 78, FirstToken = 0, - LastToken = 159, + LastToken = 160, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -483,19 +485,19 @@ declare namespace ts { LastTemplateToken = 17, FirstBinaryOperator = 29, LastBinaryOperator = 78, - FirstStatement = 236, - LastStatement = 252, - FirstNode = 160, - FirstJSDocNode = 307, - LastJSDocNode = 345, - FirstJSDocTagNode = 325, - LastJSDocTagNode = 345, + FirstStatement = 238, + LastStatement = 254, + FirstNode = 161, + FirstJSDocNode = 309, + LastJSDocNode = 347, + FirstJSDocTagNode = 327, + LastJSDocTagNode = 347, } export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; export type PseudoLiteralSyntaxKind = SyntaxKind.TemplateHead | SyntaxKind.TemplateMiddle | SyntaxKind.TemplateTail; export type PunctuationSyntaxKind = SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.OpenParenToken | SyntaxKind.CloseParenToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.DotToken | SyntaxKind.DotDotDotToken | SyntaxKind.SemicolonToken | SyntaxKind.CommaToken | SyntaxKind.QuestionDotToken | SyntaxKind.LessThanToken | SyntaxKind.LessThanSlashToken | SyntaxKind.GreaterThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.EqualsEqualsToken | SyntaxKind.ExclamationEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.EqualsGreaterThanToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.AsteriskToken | SyntaxKind.AsteriskAsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken | SyntaxKind.PlusPlusToken | SyntaxKind.MinusMinusToken | SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken | SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken | SyntaxKind.ExclamationToken | SyntaxKind.TildeToken | SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken | SyntaxKind.QuestionToken | SyntaxKind.ColonToken | SyntaxKind.AtToken | SyntaxKind.BacktickToken | SyntaxKind.HashToken | SyntaxKind.EqualsToken | SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken; - export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.AssertKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InferKeyword | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IntrinsicKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.OfKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.OverrideKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; + export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.AssertKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InferKeyword | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IntrinsicKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.OfKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.OverrideKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SatisfiesKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; export type ModifierSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.ConstKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.ExportKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.OverrideKeyword | SyntaxKind.StaticKeyword; export type KeywordTypeSyntaxKind = SyntaxKind.AnyKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.IntrinsicKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VoidKeyword; export type TokenSyntaxKind = SyntaxKind.Unknown | SyntaxKind.EndOfFileToken | TriviaSyntaxKind | LiteralSyntaxKind | PseudoLiteralSyntaxKind | PunctuationSyntaxKind | SyntaxKind.Identifier | KeywordSyntaxKind; @@ -1312,6 +1314,11 @@ declare namespace ts { readonly type: TypeNode; readonly expression: UnaryExpression; } + export interface SatisfiesExpression extends Expression { + readonly kind: SyntaxKind.SatisfiesExpression; + readonly expression: Expression; + readonly type: TypeNode; + } export type AssertionExpression = TypeAssertion | AsExpression; export interface NonNullExpression extends LeftHandSideExpression { readonly kind: SyntaxKind.NonNullExpression; @@ -3512,6 +3519,8 @@ declare namespace ts { updateNonNullChain(node: NonNullChain, expression: Expression): NonNullChain; createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty; updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty; + createSatisfiesExpression(expression: Expression, type: TypeNode): SatisfiesExpression; + updateSatisfiesExpression(node: SatisfiesExpression, expression: Expression, type: TypeNode): SatisfiesExpression; createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; createSemicolonClassElement(): SemicolonClassElement; @@ -4623,6 +4632,7 @@ declare namespace ts { function isOmittedExpression(node: Node): node is OmittedExpression; function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments; function isAsExpression(node: Node): node is AsExpression; + function isSatisfiesExpression(node: Node): node is SatisfiesExpression; function isNonNullExpression(node: Node): node is NonNullExpression; function isMetaProperty(node: Node): node is MetaProperty; function isSyntheticExpression(node: Node): node is SyntheticExpression; diff --git a/tests/baselines/reference/completionsCommentsClass.baseline b/tests/baselines/reference/completionsCommentsClass.baseline index b16322debe66b..3b82cc8020c64 100644 --- a/tests/baselines/reference/completionsCommentsClass.baseline +++ b/tests/baselines/reference/completionsCommentsClass.baseline @@ -3114,6 +3114,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "string", "kind": "keyword", diff --git a/tests/baselines/reference/completionsCommentsClassMembers.baseline b/tests/baselines/reference/completionsCommentsClassMembers.baseline index 8a4468b7da93c..d5e0d8af545ae 100644 --- a/tests/baselines/reference/completionsCommentsClassMembers.baseline +++ b/tests/baselines/reference/completionsCommentsClassMembers.baseline @@ -4046,6 +4046,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -11102,6 +11114,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -15914,6 +15938,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -22970,6 +23006,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -27034,6 +27082,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -32253,6 +32313,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -36271,6 +36343,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -41444,6 +41528,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -46663,6 +46759,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -51882,6 +51990,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -57101,6 +57221,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -61160,6 +61292,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -65219,6 +65363,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -69278,6 +69434,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -73337,6 +73505,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -77396,6 +77576,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -81455,6 +81647,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -85950,6 +86154,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "string", "kind": "keyword", @@ -91306,6 +91522,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "string", "kind": "keyword", @@ -95821,6 +96049,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", diff --git a/tests/baselines/reference/completionsCommentsCommentParsing.baseline b/tests/baselines/reference/completionsCommentsCommentParsing.baseline index 66e9516361e36..f88a1c202d4c4 100644 --- a/tests/baselines/reference/completionsCommentsCommentParsing.baseline +++ b/tests/baselines/reference/completionsCommentsCommentParsing.baseline @@ -4881,6 +4881,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -11048,6 +11060,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -16947,6 +16971,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -22587,6 +22623,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "string", "kind": "keyword", @@ -28389,6 +28437,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -34556,6 +34616,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -40472,6 +40544,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "string", "kind": "keyword", diff --git a/tests/baselines/reference/completionsCommentsFunctionDeclaration.baseline b/tests/baselines/reference/completionsCommentsFunctionDeclaration.baseline index 7a58a4e801dfd..3aa2cbb0fb5f7 100644 --- a/tests/baselines/reference/completionsCommentsFunctionDeclaration.baseline +++ b/tests/baselines/reference/completionsCommentsFunctionDeclaration.baseline @@ -3268,6 +3268,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -7020,6 +7032,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -11054,6 +11078,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", diff --git a/tests/baselines/reference/completionsCommentsFunctionExpression.baseline b/tests/baselines/reference/completionsCommentsFunctionExpression.baseline index 6184a312462d5..b71a08561f843 100644 --- a/tests/baselines/reference/completionsCommentsFunctionExpression.baseline +++ b/tests/baselines/reference/completionsCommentsFunctionExpression.baseline @@ -3021,6 +3021,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "string", "kind": "keyword", @@ -7467,6 +7479,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "string", "kind": "keyword", @@ -11469,6 +11493,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", @@ -15687,6 +15723,18 @@ } ] }, + { + "name": "satisfies", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "satisfies", + "kind": "keyword" + } + ] + }, { "name": "String", "kind": "var", diff --git a/tests/baselines/reference/jsFileCompilationTypeSatisfaction.errors.txt b/tests/baselines/reference/jsFileCompilationTypeSatisfaction.errors.txt new file mode 100644 index 0000000000000..f8f9369db84ee --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationTypeSatisfaction.errors.txt @@ -0,0 +1,8 @@ +/src/a.js(1,29): error TS8035: Type satisfaction expressions can only be used in TypeScript files. + + +==== /src/a.js (1 errors) ==== + var v = undefined satisfies 1; + ~ +!!! error TS8035: Type satisfaction expressions can only be used in TypeScript files. + \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilationTypeSatisfaction.js b/tests/baselines/reference/jsFileCompilationTypeSatisfaction.js new file mode 100644 index 0000000000000..3d28ea0e2675d --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationTypeSatisfaction.js @@ -0,0 +1,6 @@ +//// [a.js] +var v = undefined satisfies 1; + + +//// [a.js] +var v = undefined; diff --git a/tests/baselines/reference/jsFileCompilationTypeSatisfaction.symbols b/tests/baselines/reference/jsFileCompilationTypeSatisfaction.symbols new file mode 100644 index 0000000000000..e5424113f5b8b --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationTypeSatisfaction.symbols @@ -0,0 +1,5 @@ +=== /src/a.js === +var v = undefined satisfies 1; +>v : Symbol(v, Decl(a.js, 0, 3)) +>undefined : Symbol(undefined) + diff --git a/tests/baselines/reference/jsFileCompilationTypeSatisfaction.types b/tests/baselines/reference/jsFileCompilationTypeSatisfaction.types new file mode 100644 index 0000000000000..dde08ce298036 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationTypeSatisfaction.types @@ -0,0 +1,6 @@ +=== /src/a.js === +var v = undefined satisfies 1; +>v : any +>undefined satisfies 1 : undefined +>undefined : undefined + diff --git a/tests/baselines/reference/typeSatisfaction.errors.txt b/tests/baselines/reference/typeSatisfaction.errors.txt new file mode 100644 index 0000000000000..679d8574e8b8d --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction.errors.txt @@ -0,0 +1,31 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts(12,20): error TS1360: Type '{ a: number; b: number; }' does not satisfy the expected type 'I1'. + Object literal may only specify known properties, and 'b' does not exist in type 'I1'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts(13,26): error TS1360: Type '{}' does not satisfy the expected type 'I1'. + Property 'a' is missing in type '{}' but required in type 'I1'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts (2 errors) ==== + interface I1 { + a: number; + } + + type T1 = { + a: "a" | "b"; + } + + type T2 = (x: string) => void; + + const a1 = { a: 1 } satisfies I1; // Ok + const a2 = { a: 1, b: 1 } satisfies I1; // Error + ~~~~ +!!! error TS1360: Type '{ a: number; b: number; }' does not satisfy the expected type 'I1'. +!!! error TS1360: Object literal may only specify known properties, and 'b' does not exist in type 'I1'. + const a3 = { } satisfies I1; // Error + ~~ +!!! error TS1360: Type '{}' does not satisfy the expected type 'I1'. +!!! error TS1360: Property 'a' is missing in type '{}' but required in type 'I1'. +!!! related TS2728 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts:2:5: 'a' is declared here. + + const a4: T1 = { a: "a" } satisfies T1; // Ok + const a5 = (m => m.substring(0)) satisfies T2; // Ok + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction.js b/tests/baselines/reference/typeSatisfaction.js new file mode 100644 index 0000000000000..3b649039d98ea --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction.js @@ -0,0 +1,25 @@ +//// [typeSatisfaction.ts] +interface I1 { + a: number; +} + +type T1 = { + a: "a" | "b"; +} + +type T2 = (x: string) => void; + +const a1 = { a: 1 } satisfies I1; // Ok +const a2 = { a: 1, b: 1 } satisfies I1; // Error +const a3 = { } satisfies I1; // Error + +const a4: T1 = { a: "a" } satisfies T1; // Ok +const a5 = (m => m.substring(0)) satisfies T2; // Ok + + +//// [typeSatisfaction.js] +var a1 = { a: 1 }; // Ok +var a2 = { a: 1, b: 1 }; // Error +var a3 = {}; // Error +var a4 = { a: "a" }; // Ok +var a5 = (function (m) { return m.substring(0); }); // Ok diff --git a/tests/baselines/reference/typeSatisfaction.symbols b/tests/baselines/reference/typeSatisfaction.symbols new file mode 100644 index 0000000000000..2eae603562b0a --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction.symbols @@ -0,0 +1,48 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts === +interface I1 { +>I1 : Symbol(I1, Decl(typeSatisfaction.ts, 0, 0)) + + a: number; +>a : Symbol(I1.a, Decl(typeSatisfaction.ts, 0, 14)) +} + +type T1 = { +>T1 : Symbol(T1, Decl(typeSatisfaction.ts, 2, 1)) + + a: "a" | "b"; +>a : Symbol(a, Decl(typeSatisfaction.ts, 4, 11)) +} + +type T2 = (x: string) => void; +>T2 : Symbol(T2, Decl(typeSatisfaction.ts, 6, 1)) +>x : Symbol(x, Decl(typeSatisfaction.ts, 8, 11)) + +const a1 = { a: 1 } satisfies I1; // Ok +>a1 : Symbol(a1, Decl(typeSatisfaction.ts, 10, 5)) +>a : Symbol(a, Decl(typeSatisfaction.ts, 10, 12)) +>I1 : Symbol(I1, Decl(typeSatisfaction.ts, 0, 0)) + +const a2 = { a: 1, b: 1 } satisfies I1; // Error +>a2 : Symbol(a2, Decl(typeSatisfaction.ts, 11, 5)) +>a : Symbol(a, Decl(typeSatisfaction.ts, 11, 12)) +>b : Symbol(b, Decl(typeSatisfaction.ts, 11, 18)) +>I1 : Symbol(I1, Decl(typeSatisfaction.ts, 0, 0)) + +const a3 = { } satisfies I1; // Error +>a3 : Symbol(a3, Decl(typeSatisfaction.ts, 12, 5)) +>I1 : Symbol(I1, Decl(typeSatisfaction.ts, 0, 0)) + +const a4: T1 = { a: "a" } satisfies T1; // Ok +>a4 : Symbol(a4, Decl(typeSatisfaction.ts, 14, 5)) +>T1 : Symbol(T1, Decl(typeSatisfaction.ts, 2, 1)) +>a : Symbol(a, Decl(typeSatisfaction.ts, 14, 16)) +>T1 : Symbol(T1, Decl(typeSatisfaction.ts, 2, 1)) + +const a5 = (m => m.substring(0)) satisfies T2; // Ok +>a5 : Symbol(a5, Decl(typeSatisfaction.ts, 15, 5)) +>m : Symbol(m, Decl(typeSatisfaction.ts, 15, 12)) +>m.substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) +>m : Symbol(m, Decl(typeSatisfaction.ts, 15, 12)) +>substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) +>T2 : Symbol(T2, Decl(typeSatisfaction.ts, 6, 1)) + diff --git a/tests/baselines/reference/typeSatisfaction.types b/tests/baselines/reference/typeSatisfaction.types new file mode 100644 index 0000000000000..fff207ffa0534 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction.types @@ -0,0 +1,57 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts === +interface I1 { + a: number; +>a : number +} + +type T1 = { +>T1 : T1 + + a: "a" | "b"; +>a : "a" | "b" +} + +type T2 = (x: string) => void; +>T2 : T2 +>x : string + +const a1 = { a: 1 } satisfies I1; // Ok +>a1 : { a: number; } +>{ a: 1 } satisfies I1 : { a: number; } +>{ a: 1 } : { a: number; } +>a : number +>1 : 1 + +const a2 = { a: 1, b: 1 } satisfies I1; // Error +>a2 : { a: number; b: number; } +>{ a: 1, b: 1 } satisfies I1 : { a: number; b: number; } +>{ a: 1, b: 1 } : { a: number; b: number; } +>a : number +>1 : 1 +>b : number +>1 : 1 + +const a3 = { } satisfies I1; // Error +>a3 : {} +>{ } satisfies I1 : {} +>{ } : {} + +const a4: T1 = { a: "a" } satisfies T1; // Ok +>a4 : T1 +>{ a: "a" } satisfies T1 : { a: "a"; } +>{ a: "a" } : { a: "a"; } +>a : "a" +>"a" : "a" + +const a5 = (m => m.substring(0)) satisfies T2; // Ok +>a5 : (m: string) => string +>(m => m.substring(0)) satisfies T2 : (m: string) => string +>(m => m.substring(0)) : (m: string) => string +>m => m.substring(0) : (m: string) => string +>m : string +>m.substring(0) : string +>m.substring : (start: number, end?: number) => string +>m : string +>substring : (start: number, end?: number) => string +>0 : 0 + diff --git a/tests/baselines/reference/typeSatisfactionWithDefaultExport.errors.txt b/tests/baselines/reference/typeSatisfactionWithDefaultExport.errors.txt new file mode 100644 index 0000000000000..f960726de5da9 --- /dev/null +++ b/tests/baselines/reference/typeSatisfactionWithDefaultExport.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/expressions/typeSatisfaction/a.ts(4,29): error TS1360: Type '{}' does not satisfy the expected type 'Foo'. + Property 'a' is missing in type '{}' but required in type 'Foo'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/a.ts (1 errors) ==== + interface Foo { + a: number; + } + export default {} satisfies Foo; + ~~~ +!!! error TS1360: Type '{}' does not satisfy the expected type 'Foo'. +!!! error TS1360: Property 'a' is missing in type '{}' but required in type 'Foo'. +!!! related TS2728 tests/cases/conformance/expressions/typeSatisfaction/a.ts:2:5: 'a' is declared here. + +==== tests/cases/conformance/expressions/typeSatisfaction/b.ts (0 errors) ==== + interface Foo { + a: number; + } + export default { a: 1 } satisfies Foo; + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfactionWithDefaultExport.js b/tests/baselines/reference/typeSatisfactionWithDefaultExport.js new file mode 100644 index 0000000000000..ba29570420701 --- /dev/null +++ b/tests/baselines/reference/typeSatisfactionWithDefaultExport.js @@ -0,0 +1,19 @@ +//// [tests/cases/conformance/expressions/typeSatisfaction/typeSatisfactionWithDefaultExport.ts] //// + +//// [a.ts] +interface Foo { + a: number; +} +export default {} satisfies Foo; + +//// [b.ts] +interface Foo { + a: number; +} +export default { a: 1 } satisfies Foo; + + +//// [a.js] +export default {}; +//// [b.js] +export default { a: 1 }; diff --git a/tests/baselines/reference/typeSatisfactionWithDefaultExport.symbols b/tests/baselines/reference/typeSatisfactionWithDefaultExport.symbols new file mode 100644 index 0000000000000..135876487d71f --- /dev/null +++ b/tests/baselines/reference/typeSatisfactionWithDefaultExport.symbols @@ -0,0 +1,21 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/a.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(a.ts, 0, 0)) + + a: number; +>a : Symbol(Foo.a, Decl(a.ts, 0, 15)) +} +export default {} satisfies Foo; +>Foo : Symbol(Foo, Decl(a.ts, 0, 0)) + +=== tests/cases/conformance/expressions/typeSatisfaction/b.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(b.ts, 0, 0)) + + a: number; +>a : Symbol(Foo.a, Decl(b.ts, 0, 15)) +} +export default { a: 1 } satisfies Foo; +>a : Symbol(a, Decl(b.ts, 3, 16)) +>Foo : Symbol(Foo, Decl(b.ts, 0, 0)) + diff --git a/tests/baselines/reference/typeSatisfactionWithDefaultExport.types b/tests/baselines/reference/typeSatisfactionWithDefaultExport.types new file mode 100644 index 0000000000000..6f281cea3c955 --- /dev/null +++ b/tests/baselines/reference/typeSatisfactionWithDefaultExport.types @@ -0,0 +1,20 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/a.ts === +interface Foo { + a: number; +>a : number +} +export default {} satisfies Foo; +>{} satisfies Foo : {} +>{} : {} + +=== tests/cases/conformance/expressions/typeSatisfaction/b.ts === +interface Foo { + a: number; +>a : number +} +export default { a: 1 } satisfies Foo; +>{ a: 1 } satisfies Foo : { a: number; } +>{ a: 1 } : { a: number; } +>a : number +>1 : 1 + diff --git a/tests/cases/compiler/jsFileCompilationTypeSatisfaction.ts b/tests/cases/compiler/jsFileCompilationTypeSatisfaction.ts new file mode 100644 index 0000000000000..ba4701687bc08 --- /dev/null +++ b/tests/cases/compiler/jsFileCompilationTypeSatisfaction.ts @@ -0,0 +1,5 @@ +// @allowJs: true +// @filename: /src/a.js +// @out: /lib/a.js + +var v = undefined satisfies 1; diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts new file mode 100644 index 0000000000000..fa60720e297bb --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts @@ -0,0 +1,16 @@ +interface I1 { + a: number; +} + +type T1 = { + a: "a" | "b"; +} + +type T2 = (x: string) => void; + +const a1 = { a: 1 } satisfies I1; // Ok +const a2 = { a: 1, b: 1 } satisfies I1; // Error +const a3 = { } satisfies I1; // Error + +const a4: T1 = { a: "a" } satisfies T1; // Ok +const a5 = (m => m.substring(0)) satisfies T2; // Ok diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfactionWithDefaultExport.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfactionWithDefaultExport.ts new file mode 100644 index 0000000000000..247accb875863 --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfactionWithDefaultExport.ts @@ -0,0 +1,13 @@ +// @module: esnext + +// @filename: ./a.ts +interface Foo { + a: number; +} +export default {} satisfies Foo; + +// @filename: ./b.ts +interface Foo { + a: number; +} +export default { a: 1 } satisfies Foo; diff --git a/tests/cases/fourslash/completionSatisfiesKeyword.ts b/tests/cases/fourslash/completionSatisfiesKeyword.ts new file mode 100644 index 0000000000000..c44ca016c3f6f --- /dev/null +++ b/tests/cases/fourslash/completionSatisfiesKeyword.ts @@ -0,0 +1,11 @@ +/// + +////const x = { a: 1 } /*1*/ +////function foo() { +//// const x = { a: 1 } /*2*/ +////} + +verify.completions({ + marker: ["1", "2"], + includes: [{ name: "satisfies", sortText: completion.SortText.GlobalsOrKeywords }] +}); diff --git a/tests/cases/fourslash/satisfiesOperatorCompletion.ts b/tests/cases/fourslash/satisfiesOperatorCompletion.ts new file mode 100644 index 0000000000000..94b07db40da32 --- /dev/null +++ b/tests/cases/fourslash/satisfiesOperatorCompletion.ts @@ -0,0 +1,7 @@ +/// + +//// type T = number; +//// var x; +//// var y = x satisfies /**/ + +verify.completions({ marker: "", includes: "T" }); From d09c6c6fbd3ae62d3089d2e6db5b4ce0ad5ecbb7 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 17 Mar 2022 15:06:49 -0700 Subject: [PATCH 02/11] Add failing test for lack of intersectioned contextual type --- .../satisfiesContextualType.errors.txt | 11 ++++++++++ .../reference/satisfiesContextualType.js | 13 ++++++++++++ .../reference/satisfiesContextualType.symbols | 20 +++++++++++++++++++ .../reference/satisfiesContextualType.types | 20 +++++++++++++++++++ .../cases/compiler/satisfiesContextualType.ts | 6 ++++++ 5 files changed, 70 insertions(+) create mode 100644 tests/baselines/reference/satisfiesContextualType.errors.txt create mode 100644 tests/baselines/reference/satisfiesContextualType.js create mode 100644 tests/baselines/reference/satisfiesContextualType.symbols create mode 100644 tests/baselines/reference/satisfiesContextualType.types create mode 100644 tests/cases/compiler/satisfiesContextualType.ts diff --git a/tests/baselines/reference/satisfiesContextualType.errors.txt b/tests/baselines/reference/satisfiesContextualType.errors.txt new file mode 100644 index 0000000000000..d93b9f249c07f --- /dev/null +++ b/tests/baselines/reference/satisfiesContextualType.errors.txt @@ -0,0 +1,11 @@ +tests/cases/compiler/satisfiesContextualType.ts(2,7): error TS7006: Parameter 's' implicitly has an 'any' type. + + +==== tests/cases/compiler/satisfiesContextualType.ts (1 errors) ==== + let obj: { f(s: string): void } & Record = { + f(s) { }, // "incorrect" implicit any on 's' + ~ +!!! error TS7006: Parameter 's' implicitly has an 'any' type. + g(s) { } + } satisfies { g(s: string): void } & Record; + \ No newline at end of file diff --git a/tests/baselines/reference/satisfiesContextualType.js b/tests/baselines/reference/satisfiesContextualType.js new file mode 100644 index 0000000000000..b138c42e96533 --- /dev/null +++ b/tests/baselines/reference/satisfiesContextualType.js @@ -0,0 +1,13 @@ +//// [satisfiesContextualType.ts] +let obj: { f(s: string): void } & Record = { + f(s) { }, // "incorrect" implicit any on 's' + g(s) { } +} satisfies { g(s: string): void } & Record; + + +//// [satisfiesContextualType.js] +"use strict"; +var obj = { + f: function (s) { }, + g: function (s) { } +}; diff --git a/tests/baselines/reference/satisfiesContextualType.symbols b/tests/baselines/reference/satisfiesContextualType.symbols new file mode 100644 index 0000000000000..3837551a8a05a --- /dev/null +++ b/tests/baselines/reference/satisfiesContextualType.symbols @@ -0,0 +1,20 @@ +=== tests/cases/compiler/satisfiesContextualType.ts === +let obj: { f(s: string): void } & Record = { +>obj : Symbol(obj, Decl(satisfiesContextualType.ts, 0, 3)) +>f : Symbol(f, Decl(satisfiesContextualType.ts, 0, 10)) +>s : Symbol(s, Decl(satisfiesContextualType.ts, 0, 13)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + + f(s) { }, // "incorrect" implicit any on 's' +>f : Symbol(f, Decl(satisfiesContextualType.ts, 0, 61)) +>s : Symbol(s, Decl(satisfiesContextualType.ts, 1, 6)) + + g(s) { } +>g : Symbol(g, Decl(satisfiesContextualType.ts, 1, 13)) +>s : Symbol(s, Decl(satisfiesContextualType.ts, 2, 6)) + +} satisfies { g(s: string): void } & Record; +>g : Symbol(g, Decl(satisfiesContextualType.ts, 3, 13)) +>s : Symbol(s, Decl(satisfiesContextualType.ts, 3, 16)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + diff --git a/tests/baselines/reference/satisfiesContextualType.types b/tests/baselines/reference/satisfiesContextualType.types new file mode 100644 index 0000000000000..2aab9505bd6a1 --- /dev/null +++ b/tests/baselines/reference/satisfiesContextualType.types @@ -0,0 +1,20 @@ +=== tests/cases/compiler/satisfiesContextualType.ts === +let obj: { f(s: string): void } & Record = { +>obj : { f(s: string): void; } & Record +>f : (s: string) => void +>s : string +>{ f(s) { }, // "incorrect" implicit any on 's' g(s) { }} satisfies { g(s: string): void } & Record : { f(s: any): void; g(s: string): void; } +>{ f(s) { }, // "incorrect" implicit any on 's' g(s) { }} : { f(s: any): void; g(s: string): void; } + + f(s) { }, // "incorrect" implicit any on 's' +>f : (s: any) => void +>s : any + + g(s) { } +>g : (s: string) => void +>s : string + +} satisfies { g(s: string): void } & Record; +>g : (s: string) => void +>s : string + diff --git a/tests/cases/compiler/satisfiesContextualType.ts b/tests/cases/compiler/satisfiesContextualType.ts new file mode 100644 index 0000000000000..168f14d264545 --- /dev/null +++ b/tests/cases/compiler/satisfiesContextualType.ts @@ -0,0 +1,6 @@ +// @strict: true + +let obj: { f(s: string): void } & Record = { + f(s) { }, // "incorrect" implicit any on 's' + g(s) { } +} satisfies { g(s: string): void } & Record; From ee8e50e4db133e49ba315ae43e0fc1b1a6f7a616 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 17 Mar 2022 15:12:29 -0700 Subject: [PATCH 03/11] Implement the behavior --- src/compiler/checker.ts | 7 ++++++- .../reference/satisfiesContextualType.errors.txt | 11 ----------- .../baselines/reference/satisfiesContextualType.types | 8 ++++---- 3 files changed, 10 insertions(+), 16 deletions(-) delete mode 100644 tests/baselines/reference/satisfiesContextualType.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b778dbae1f8c7..e8a45ad07869a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26991,7 +26991,12 @@ namespace ts { case SyntaxKind.NonNullExpression: return getContextualType(parent as NonNullExpression, contextFlags); case SyntaxKind.SatisfiesExpression: - return getTypeFromTypeNode((parent as SatisfiesExpression).type); + const assertedType = getTypeFromTypeNode((parent as SatisfiesExpression).type); + const outerType = isExpression(parent) ? getContextualType(parent) : undefined; + if (outerType !== undefined) { + return getIntersectionType([assertedType, outerType]); + } + return assertedType; case SyntaxKind.ExportAssignment: return tryGetTypeFromEffectiveTypeNode(parent as ExportAssignment); case SyntaxKind.JsxExpression: diff --git a/tests/baselines/reference/satisfiesContextualType.errors.txt b/tests/baselines/reference/satisfiesContextualType.errors.txt deleted file mode 100644 index d93b9f249c07f..0000000000000 --- a/tests/baselines/reference/satisfiesContextualType.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -tests/cases/compiler/satisfiesContextualType.ts(2,7): error TS7006: Parameter 's' implicitly has an 'any' type. - - -==== tests/cases/compiler/satisfiesContextualType.ts (1 errors) ==== - let obj: { f(s: string): void } & Record = { - f(s) { }, // "incorrect" implicit any on 's' - ~ -!!! error TS7006: Parameter 's' implicitly has an 'any' type. - g(s) { } - } satisfies { g(s: string): void } & Record; - \ No newline at end of file diff --git a/tests/baselines/reference/satisfiesContextualType.types b/tests/baselines/reference/satisfiesContextualType.types index 2aab9505bd6a1..2e4330f13432e 100644 --- a/tests/baselines/reference/satisfiesContextualType.types +++ b/tests/baselines/reference/satisfiesContextualType.types @@ -3,12 +3,12 @@ let obj: { f(s: string): void } & Record = { >obj : { f(s: string): void; } & Record >f : (s: string) => void >s : string ->{ f(s) { }, // "incorrect" implicit any on 's' g(s) { }} satisfies { g(s: string): void } & Record : { f(s: any): void; g(s: string): void; } ->{ f(s) { }, // "incorrect" implicit any on 's' g(s) { }} : { f(s: any): void; g(s: string): void; } +>{ f(s) { }, // "incorrect" implicit any on 's' g(s) { }} satisfies { g(s: string): void } & Record : { f(s: string): void; g(s: string): void; } +>{ f(s) { }, // "incorrect" implicit any on 's' g(s) { }} : { f(s: string): void; g(s: string): void; } f(s) { }, // "incorrect" implicit any on 's' ->f : (s: any) => void ->s : any +>f : (s: string) => void +>s : string g(s) { } >g : (s: string) => void From d810a021e0bb049cb5faa07141ae3b7ba8be8567 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 17 Mar 2022 15:12:49 -0700 Subject: [PATCH 04/11] Add test corresponding to the 'if' --- tests/baselines/reference/satisfiesContextualType.js | 5 +++++ .../reference/satisfiesContextualType.symbols | 7 +++++++ .../baselines/reference/satisfiesContextualType.types | 10 ++++++++++ tests/cases/compiler/satisfiesContextualType.ts | 3 +++ 4 files changed, 25 insertions(+) diff --git a/tests/baselines/reference/satisfiesContextualType.js b/tests/baselines/reference/satisfiesContextualType.js index b138c42e96533..656885d6409a4 100644 --- a/tests/baselines/reference/satisfiesContextualType.js +++ b/tests/baselines/reference/satisfiesContextualType.js @@ -3,6 +3,9 @@ let obj: { f(s: string): void } & Record = { f(s) { }, // "incorrect" implicit any on 's' g(s) { } } satisfies { g(s: string): void } & Record; + +// This needs to not crash (outer node is not expression) +({ f(x) { } }) satisfies { f(s: string): void }; //// [satisfiesContextualType.js] @@ -11,3 +14,5 @@ var obj = { f: function (s) { }, g: function (s) { } }; +// This needs to not crash (outer node is not expression) +({ f: function (x) { } }); diff --git a/tests/baselines/reference/satisfiesContextualType.symbols b/tests/baselines/reference/satisfiesContextualType.symbols index 3837551a8a05a..1dd96046d890d 100644 --- a/tests/baselines/reference/satisfiesContextualType.symbols +++ b/tests/baselines/reference/satisfiesContextualType.symbols @@ -18,3 +18,10 @@ let obj: { f(s: string): void } & Record = { >s : Symbol(s, Decl(satisfiesContextualType.ts, 3, 16)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +// This needs to not crash (outer node is not expression) +({ f(x) { } }) satisfies { f(s: string): void }; +>f : Symbol(f, Decl(satisfiesContextualType.ts, 6, 2)) +>x : Symbol(x, Decl(satisfiesContextualType.ts, 6, 5)) +>f : Symbol(f, Decl(satisfiesContextualType.ts, 6, 26)) +>s : Symbol(s, Decl(satisfiesContextualType.ts, 6, 29)) + diff --git a/tests/baselines/reference/satisfiesContextualType.types b/tests/baselines/reference/satisfiesContextualType.types index 2e4330f13432e..a1d995063054e 100644 --- a/tests/baselines/reference/satisfiesContextualType.types +++ b/tests/baselines/reference/satisfiesContextualType.types @@ -18,3 +18,13 @@ let obj: { f(s: string): void } & Record = { >g : (s: string) => void >s : string +// This needs to not crash (outer node is not expression) +({ f(x) { } }) satisfies { f(s: string): void }; +>({ f(x) { } }) satisfies { f(s: string): void } : { f(x: string): void; } +>({ f(x) { } }) : { f(x: string): void; } +>{ f(x) { } } : { f(x: string): void; } +>f : (x: string) => void +>x : string +>f : (s: string) => void +>s : string + diff --git a/tests/cases/compiler/satisfiesContextualType.ts b/tests/cases/compiler/satisfiesContextualType.ts index 168f14d264545..f3768efb848b9 100644 --- a/tests/cases/compiler/satisfiesContextualType.ts +++ b/tests/cases/compiler/satisfiesContextualType.ts @@ -4,3 +4,6 @@ let obj: { f(s: string): void } & Record = { f(s) { }, // "incorrect" implicit any on 's' g(s) { } } satisfies { g(s: string): void } & Record; + +// This needs to not crash (outer node is not expression) +({ f(x) { } }) satisfies { f(s: string): void }; From bdd6b3e8da3e19450aafb6d943dd177f4078756e Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 17 Mar 2022 15:25:24 -0700 Subject: [PATCH 05/11] Add test based on defined scenarios --- .../reference/satisfiesScenarios.errors.txt | 150 ++++++++ .../baselines/reference/satisfiesScenarios.js | 198 ++++++++++ .../reference/satisfiesScenarios.symbols | 305 +++++++++++++++ .../reference/satisfiesScenarios.types | 363 ++++++++++++++++++ tests/cases/compiler/satisfiesScenarios.ts | 112 ++++++ 5 files changed, 1128 insertions(+) create mode 100644 tests/baselines/reference/satisfiesScenarios.errors.txt create mode 100644 tests/baselines/reference/satisfiesScenarios.js create mode 100644 tests/baselines/reference/satisfiesScenarios.symbols create mode 100644 tests/baselines/reference/satisfiesScenarios.types create mode 100644 tests/cases/compiler/satisfiesScenarios.ts diff --git a/tests/baselines/reference/satisfiesScenarios.errors.txt b/tests/baselines/reference/satisfiesScenarios.errors.txt new file mode 100644 index 0000000000000..ea637b3467df2 --- /dev/null +++ b/tests/baselines/reference/satisfiesScenarios.errors.txt @@ -0,0 +1,150 @@ +tests/cases/compiler/satisfiesScenarios.ts(7,22): error TS1360: Type '{ a: string; b: string; }' does not satisfy the expected type 'A'. + Object literal may only specify known properties, and 'b' does not exist in type 'A'. +tests/cases/compiler/satisfiesScenarios.ts(16,9): error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Partial>'. + Object literal may only specify known properties, and 'x' does not exist in type 'Partial>'. +tests/cases/compiler/satisfiesScenarios.ts(23,15): error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. +tests/cases/compiler/satisfiesScenarios.ts(32,9): error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Record'. + Object literal may only specify known properties, and 'x' does not exist in type 'Record'. +tests/cases/compiler/satisfiesScenarios.ts(39,15): error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. +tests/cases/compiler/satisfiesScenarios.ts(55,19): error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. +tests/cases/compiler/satisfiesScenarios.ts(65,9): error TS2322: Type 'string' is not assignable to type 'boolean'. +tests/cases/compiler/satisfiesScenarios.ts(75,30): error TS2322: Type '{ r: number; g: number; d: number; }' is not assignable to type 'Color'. + Object literal may only specify known properties, and 'd' does not exist in type 'Color'. +tests/cases/compiler/satisfiesScenarios.ts(101,15): error TS2339: Property 'y' does not exist on type '{ x: number; }'. + + +==== tests/cases/compiler/satisfiesScenarios.ts (9 errors) ==== + const x = [1, 2] satisfies [number, number]; + + interface A { + a: string + } + let d = { a: 'test' } satisfies A; + let e = { a: 'test', b: 'test' } satisfies A; + ~~~~~~~~~ +!!! error TS1360: Type '{ a: string; b: string; }' does not satisfy the expected type 'A'. +!!! error TS1360: Object literal may only specify known properties, and 'b' does not exist in type 'A'. + + // Most examples from #47920 + namespace PropNameConstraining { + type Keys = 'a' | 'b' | 'c' | 'd'; + + const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' + ~~~~ +!!! error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Partial>'. +!!! error TS1360: Object literal may only specify known properties, and 'x' does not exist in type 'Partial>'. + } satisfies Partial>; + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); + let b = p.b.substring(1); + // Should error even though 'd' is in 'Keys' + let d = p.d; + ~ +!!! error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. + } + + namespace PropertyNameFulfillment { + type Keys = 'a' | 'b' | 'c' | 'd'; + + const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' + ~~~~ +!!! error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Record'. +!!! error TS1360: Object literal may only specify known properties, and 'x' does not exist in type 'Record'. + } satisfies Record; + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); + let b = p.b.substr(1); + // Should error even though 'd' is in 'Keys' + let d = p.d; + ~ +!!! error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. + } + + namespace PropertyValueConformance { + type Facts = { [key: string]: boolean }; + declare function checkTruths(x: Facts): void; + declare function checkM(x: { m: boolean }): void; + const x = { + m: true + }; + + // Should be OK + checkTruths(x); + // Should be OK + checkM(x); + // Should fail under --noIndexSignaturePropertyAccess + console.log(x.z); + ~ +!!! error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. + // Should be OK under --noUncheckedIndexedAccess + const m: boolean = x.m; + + // Should be 'm' + type M = keyof typeof x; + + // Should be able to detect a failure here + const x2 = { + m: true, + s: "false" + ~ +!!! error TS2322: Type 'string' is not assignable to type 'boolean'. +!!! related TS6501 tests/cases/compiler/satisfiesScenarios.ts:43:20: The expected type comes from this index signature. + } satisfies Facts; + } + + namespace PropertyValueConformance2 { + export type Color = { r: number, g: number, b: number }; + + // All of these should be Colors, but I only use some of them here. + export const Palette = { + white: { r: 255, g: 255, b: 255 }, + black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' + ~~~~ +!!! error TS2322: Type '{ r: number; g: number; d: number; }' is not assignable to type 'Color'. +!!! error TS2322: Object literal may only specify known properties, and 'd' does not exist in type 'Color'. + blue: { r: 0, g: 0, b: 255 }, + } satisfies Record; + } + + namespace EnsureInterfaceImpl { + type Movable = { + move(distance: number): void; + }; + + const car = { + start() { }, + move(d) { + // d should be number + }, + stop() { } + } satisfies Movable & Record; + } + + namespace OptionalMemberConformance { + type Point2d = { x: number, y: number }; + // Undesirable behavior today with type annotation + const a = { x: 10 } satisfies Partial; + // Should OK + console.log(a.x.toFixed()); + // Should error + let p = a.y; + ~ +!!! error TS2339: Property 'y' does not exist on type '{ x: number; }'. + } + + namespace ContextualTyping { + type Predicates = { [s: string]: (n: number) => boolean }; + + const p: Predicates = { + isEven: n => n % 2 === 0, + isOdd: n => n % 2 === 1 + }; + } \ No newline at end of file diff --git a/tests/baselines/reference/satisfiesScenarios.js b/tests/baselines/reference/satisfiesScenarios.js new file mode 100644 index 0000000000000..2fb613887b277 --- /dev/null +++ b/tests/baselines/reference/satisfiesScenarios.js @@ -0,0 +1,198 @@ +//// [satisfiesScenarios.ts] +const x = [1, 2] satisfies [number, number]; + +interface A { + a: string +} +let d = { a: 'test' } satisfies A; +let e = { a: 'test', b: 'test' } satisfies A; + +// Most examples from #47920 +namespace PropNameConstraining { + type Keys = 'a' | 'b' | 'c' | 'd'; + + const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' + } satisfies Partial>; + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); + let b = p.b.substring(1); + // Should error even though 'd' is in 'Keys' + let d = p.d; +} + +namespace PropertyNameFulfillment { + type Keys = 'a' | 'b' | 'c' | 'd'; + + const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' + } satisfies Record; + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); + let b = p.b.substr(1); + // Should error even though 'd' is in 'Keys' + let d = p.d; +} + +namespace PropertyValueConformance { + type Facts = { [key: string]: boolean }; + declare function checkTruths(x: Facts): void; + declare function checkM(x: { m: boolean }): void; + const x = { + m: true + }; + + // Should be OK + checkTruths(x); + // Should be OK + checkM(x); + // Should fail under --noIndexSignaturePropertyAccess + console.log(x.z); + // Should be OK under --noUncheckedIndexedAccess + const m: boolean = x.m; + + // Should be 'm' + type M = keyof typeof x; + + // Should be able to detect a failure here + const x2 = { + m: true, + s: "false" + } satisfies Facts; +} + +namespace PropertyValueConformance2 { + export type Color = { r: number, g: number, b: number }; + + // All of these should be Colors, but I only use some of them here. + export const Palette = { + white: { r: 255, g: 255, b: 255 }, + black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' + blue: { r: 0, g: 0, b: 255 }, + } satisfies Record; +} + +namespace EnsureInterfaceImpl { + type Movable = { + move(distance: number): void; + }; + + const car = { + start() { }, + move(d) { + // d should be number + }, + stop() { } + } satisfies Movable & Record; +} + +namespace OptionalMemberConformance { + type Point2d = { x: number, y: number }; + // Undesirable behavior today with type annotation + const a = { x: 10 } satisfies Partial; + // Should OK + console.log(a.x.toFixed()); + // Should error + let p = a.y; +} + +namespace ContextualTyping { + type Predicates = { [s: string]: (n: number) => boolean }; + + const p: Predicates = { + isEven: n => n % 2 === 0, + isOdd: n => n % 2 === 1 + }; +} + +//// [satisfiesScenarios.js] +var x = [1, 2]; +var d = { a: 'test' }; +var e = { a: 'test', b: 'test' }; +// Most examples from #47920 +var PropNameConstraining; +(function (PropNameConstraining) { + var p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' + }; + // Should be OK -- retain info that a is number and b is string + var a = p.a.toFixed(); + var b = p.b.substring(1); + // Should error even though 'd' is in 'Keys' + var d = p.d; +})(PropNameConstraining || (PropNameConstraining = {})); +var PropertyNameFulfillment; +(function (PropertyNameFulfillment) { + var p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' + }; + // Should be OK -- retain info that a is number and b is string + var a = p.a.toFixed(); + var b = p.b.substr(1); + // Should error even though 'd' is in 'Keys' + var d = p.d; +})(PropertyNameFulfillment || (PropertyNameFulfillment = {})); +var PropertyValueConformance; +(function (PropertyValueConformance) { + var x = { + m: true + }; + // Should be OK + checkTruths(x); + // Should be OK + checkM(x); + // Should fail under --noIndexSignaturePropertyAccess + console.log(x.z); + // Should be OK under --noUncheckedIndexedAccess + var m = x.m; + // Should be able to detect a failure here + var x2 = { + m: true, + s: "false" + }; +})(PropertyValueConformance || (PropertyValueConformance = {})); +var PropertyValueConformance2; +(function (PropertyValueConformance2) { + // All of these should be Colors, but I only use some of them here. + PropertyValueConformance2.Palette = { + white: { r: 255, g: 255, b: 255 }, + black: { r: 0, g: 0, d: 0 }, + blue: { r: 0, g: 0, b: 255 } + }; +})(PropertyValueConformance2 || (PropertyValueConformance2 = {})); +var EnsureInterfaceImpl; +(function (EnsureInterfaceImpl) { + var car = { + start: function () { }, + move: function (d) { + // d should be number + }, + stop: function () { } + }; +})(EnsureInterfaceImpl || (EnsureInterfaceImpl = {})); +var OptionalMemberConformance; +(function (OptionalMemberConformance) { + // Undesirable behavior today with type annotation + var a = { x: 10 }; + // Should OK + console.log(a.x.toFixed()); + // Should error + var p = a.y; +})(OptionalMemberConformance || (OptionalMemberConformance = {})); +var ContextualTyping; +(function (ContextualTyping) { + var p = { + isEven: function (n) { return n % 2 === 0; }, + isOdd: function (n) { return n % 2 === 1; } + }; +})(ContextualTyping || (ContextualTyping = {})); diff --git a/tests/baselines/reference/satisfiesScenarios.symbols b/tests/baselines/reference/satisfiesScenarios.symbols new file mode 100644 index 0000000000000..5b71015ee8da3 --- /dev/null +++ b/tests/baselines/reference/satisfiesScenarios.symbols @@ -0,0 +1,305 @@ +=== tests/cases/compiler/satisfiesScenarios.ts === +const x = [1, 2] satisfies [number, number]; +>x : Symbol(x, Decl(satisfiesScenarios.ts, 0, 5)) + +interface A { +>A : Symbol(A, Decl(satisfiesScenarios.ts, 0, 44)) + + a: string +>a : Symbol(A.a, Decl(satisfiesScenarios.ts, 2, 13)) +} +let d = { a: 'test' } satisfies A; +>d : Symbol(d, Decl(satisfiesScenarios.ts, 5, 3)) +>a : Symbol(a, Decl(satisfiesScenarios.ts, 5, 9)) +>A : Symbol(A, Decl(satisfiesScenarios.ts, 0, 44)) + +let e = { a: 'test', b: 'test' } satisfies A; +>e : Symbol(e, Decl(satisfiesScenarios.ts, 6, 3)) +>a : Symbol(a, Decl(satisfiesScenarios.ts, 6, 9)) +>b : Symbol(b, Decl(satisfiesScenarios.ts, 6, 20)) +>A : Symbol(A, Decl(satisfiesScenarios.ts, 0, 44)) + +// Most examples from #47920 +namespace PropNameConstraining { +>PropNameConstraining : Symbol(PropNameConstraining, Decl(satisfiesScenarios.ts, 6, 45)) + + type Keys = 'a' | 'b' | 'c' | 'd'; +>Keys : Symbol(Keys, Decl(satisfiesScenarios.ts, 9, 32)) + + const p = { +>p : Symbol(p, Decl(satisfiesScenarios.ts, 12, 9)) + + a: 0, +>a : Symbol(a, Decl(satisfiesScenarios.ts, 12, 15)) + + b: "hello", +>b : Symbol(b, Decl(satisfiesScenarios.ts, 13, 13)) + + x: 8 // Should error, 'x' isn't in 'Keys' +>x : Symbol(x, Decl(satisfiesScenarios.ts, 14, 19)) + + } satisfies Partial>; +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>Keys : Symbol(Keys, Decl(satisfiesScenarios.ts, 9, 32)) + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); +>a : Symbol(a, Decl(satisfiesScenarios.ts, 19, 7)) +>p.a.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>p.a : Symbol(a, Decl(satisfiesScenarios.ts, 12, 15)) +>p : Symbol(p, Decl(satisfiesScenarios.ts, 12, 9)) +>a : Symbol(a, Decl(satisfiesScenarios.ts, 12, 15)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + let b = p.b.substring(1); +>b : Symbol(b, Decl(satisfiesScenarios.ts, 20, 7)) +>p.b.substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) +>p.b : Symbol(b, Decl(satisfiesScenarios.ts, 13, 13)) +>p : Symbol(p, Decl(satisfiesScenarios.ts, 12, 9)) +>b : Symbol(b, Decl(satisfiesScenarios.ts, 13, 13)) +>substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) + + // Should error even though 'd' is in 'Keys' + let d = p.d; +>d : Symbol(d, Decl(satisfiesScenarios.ts, 22, 7)) +>p : Symbol(p, Decl(satisfiesScenarios.ts, 12, 9)) +} + +namespace PropertyNameFulfillment { +>PropertyNameFulfillment : Symbol(PropertyNameFulfillment, Decl(satisfiesScenarios.ts, 23, 1)) + + type Keys = 'a' | 'b' | 'c' | 'd'; +>Keys : Symbol(Keys, Decl(satisfiesScenarios.ts, 25, 35)) + + const p = { +>p : Symbol(p, Decl(satisfiesScenarios.ts, 28, 9)) + + a: 0, +>a : Symbol(a, Decl(satisfiesScenarios.ts, 28, 15)) + + b: "hello", +>b : Symbol(b, Decl(satisfiesScenarios.ts, 29, 13)) + + x: 8 // Should error, 'x' isn't in 'Keys' +>x : Symbol(x, Decl(satisfiesScenarios.ts, 30, 19)) + + } satisfies Record; +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>Keys : Symbol(Keys, Decl(satisfiesScenarios.ts, 25, 35)) + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); +>a : Symbol(a, Decl(satisfiesScenarios.ts, 35, 7)) +>p.a.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>p.a : Symbol(a, Decl(satisfiesScenarios.ts, 28, 15)) +>p : Symbol(p, Decl(satisfiesScenarios.ts, 28, 9)) +>a : Symbol(a, Decl(satisfiesScenarios.ts, 28, 15)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + let b = p.b.substr(1); +>b : Symbol(b, Decl(satisfiesScenarios.ts, 36, 7)) +>p.b.substr : Symbol(String.substr, Decl(lib.es5.d.ts, --, --)) +>p.b : Symbol(b, Decl(satisfiesScenarios.ts, 29, 13)) +>p : Symbol(p, Decl(satisfiesScenarios.ts, 28, 9)) +>b : Symbol(b, Decl(satisfiesScenarios.ts, 29, 13)) +>substr : Symbol(String.substr, Decl(lib.es5.d.ts, --, --)) + + // Should error even though 'd' is in 'Keys' + let d = p.d; +>d : Symbol(d, Decl(satisfiesScenarios.ts, 38, 7)) +>p : Symbol(p, Decl(satisfiesScenarios.ts, 28, 9)) +} + +namespace PropertyValueConformance { +>PropertyValueConformance : Symbol(PropertyValueConformance, Decl(satisfiesScenarios.ts, 39, 1)) + + type Facts = { [key: string]: boolean }; +>Facts : Symbol(Facts, Decl(satisfiesScenarios.ts, 41, 36)) +>key : Symbol(key, Decl(satisfiesScenarios.ts, 42, 20)) + + declare function checkTruths(x: Facts): void; +>checkTruths : Symbol(checkTruths, Decl(satisfiesScenarios.ts, 42, 44)) +>x : Symbol(x, Decl(satisfiesScenarios.ts, 43, 33)) +>Facts : Symbol(Facts, Decl(satisfiesScenarios.ts, 41, 36)) + + declare function checkM(x: { m: boolean }): void; +>checkM : Symbol(checkM, Decl(satisfiesScenarios.ts, 43, 49)) +>x : Symbol(x, Decl(satisfiesScenarios.ts, 44, 28)) +>m : Symbol(m, Decl(satisfiesScenarios.ts, 44, 32)) + + const x = { +>x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) + + m: true +>m : Symbol(m, Decl(satisfiesScenarios.ts, 45, 15)) + + }; + + // Should be OK + checkTruths(x); +>checkTruths : Symbol(checkTruths, Decl(satisfiesScenarios.ts, 42, 44)) +>x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) + + // Should be OK + checkM(x); +>checkM : Symbol(checkM, Decl(satisfiesScenarios.ts, 43, 49)) +>x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) + + // Should fail under --noIndexSignaturePropertyAccess + console.log(x.z); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) + + // Should be OK under --noUncheckedIndexedAccess + const m: boolean = x.m; +>m : Symbol(m, Decl(satisfiesScenarios.ts, 56, 9)) +>x.m : Symbol(m, Decl(satisfiesScenarios.ts, 45, 15)) +>x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) +>m : Symbol(m, Decl(satisfiesScenarios.ts, 45, 15)) + + // Should be 'm' + type M = keyof typeof x; +>M : Symbol(M, Decl(satisfiesScenarios.ts, 56, 27)) +>x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) + + // Should be able to detect a failure here + const x2 = { +>x2 : Symbol(x2, Decl(satisfiesScenarios.ts, 62, 9)) + + m: true, +>m : Symbol(m, Decl(satisfiesScenarios.ts, 62, 16)) + + s: "false" +>s : Symbol(s, Decl(satisfiesScenarios.ts, 63, 16)) + + } satisfies Facts; +>Facts : Symbol(Facts, Decl(satisfiesScenarios.ts, 41, 36)) +} + +namespace PropertyValueConformance2 { +>PropertyValueConformance2 : Symbol(PropertyValueConformance2, Decl(satisfiesScenarios.ts, 66, 1)) + + export type Color = { r: number, g: number, b: number }; +>Color : Symbol(Color, Decl(satisfiesScenarios.ts, 68, 37)) +>r : Symbol(r, Decl(satisfiesScenarios.ts, 69, 25)) +>g : Symbol(g, Decl(satisfiesScenarios.ts, 69, 36)) +>b : Symbol(b, Decl(satisfiesScenarios.ts, 69, 47)) + + // All of these should be Colors, but I only use some of them here. + export const Palette = { +>Palette : Symbol(Palette, Decl(satisfiesScenarios.ts, 72, 16)) + + white: { r: 255, g: 255, b: 255 }, +>white : Symbol(white, Decl(satisfiesScenarios.ts, 72, 28)) +>r : Symbol(r, Decl(satisfiesScenarios.ts, 73, 16)) +>g : Symbol(g, Decl(satisfiesScenarios.ts, 73, 24)) +>b : Symbol(b, Decl(satisfiesScenarios.ts, 73, 32)) + + black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' +>black : Symbol(black, Decl(satisfiesScenarios.ts, 73, 42)) +>r : Symbol(r, Decl(satisfiesScenarios.ts, 74, 16)) +>g : Symbol(g, Decl(satisfiesScenarios.ts, 74, 22)) +>d : Symbol(d, Decl(satisfiesScenarios.ts, 74, 28)) + + blue: { r: 0, g: 0, b: 255 }, +>blue : Symbol(blue, Decl(satisfiesScenarios.ts, 74, 36)) +>r : Symbol(r, Decl(satisfiesScenarios.ts, 75, 15)) +>g : Symbol(g, Decl(satisfiesScenarios.ts, 75, 21)) +>b : Symbol(b, Decl(satisfiesScenarios.ts, 75, 27)) + + } satisfies Record; +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>Color : Symbol(Color, Decl(satisfiesScenarios.ts, 68, 37)) +} + +namespace EnsureInterfaceImpl { +>EnsureInterfaceImpl : Symbol(EnsureInterfaceImpl, Decl(satisfiesScenarios.ts, 77, 1)) + + type Movable = { +>Movable : Symbol(Movable, Decl(satisfiesScenarios.ts, 79, 31)) + + move(distance: number): void; +>move : Symbol(move, Decl(satisfiesScenarios.ts, 80, 20)) +>distance : Symbol(distance, Decl(satisfiesScenarios.ts, 81, 13)) + + }; + + const car = { +>car : Symbol(car, Decl(satisfiesScenarios.ts, 84, 9)) + + start() { }, +>start : Symbol(start, Decl(satisfiesScenarios.ts, 84, 17)) + + move(d) { +>move : Symbol(move, Decl(satisfiesScenarios.ts, 85, 20)) +>d : Symbol(d, Decl(satisfiesScenarios.ts, 86, 13)) + + // d should be number + }, + stop() { } +>stop : Symbol(stop, Decl(satisfiesScenarios.ts, 88, 10)) + + } satisfies Movable & Record; +>Movable : Symbol(Movable, Decl(satisfiesScenarios.ts, 79, 31)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +} + +namespace OptionalMemberConformance { +>OptionalMemberConformance : Symbol(OptionalMemberConformance, Decl(satisfiesScenarios.ts, 91, 1)) + + type Point2d = { x: number, y: number }; +>Point2d : Symbol(Point2d, Decl(satisfiesScenarios.ts, 93, 37)) +>x : Symbol(x, Decl(satisfiesScenarios.ts, 94, 20)) +>y : Symbol(y, Decl(satisfiesScenarios.ts, 94, 31)) + + // Undesirable behavior today with type annotation + const a = { x: 10 } satisfies Partial; +>a : Symbol(a, Decl(satisfiesScenarios.ts, 96, 9)) +>x : Symbol(x, Decl(satisfiesScenarios.ts, 96, 15)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>Point2d : Symbol(Point2d, Decl(satisfiesScenarios.ts, 93, 37)) + + // Should OK + console.log(a.x.toFixed()); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>a.x.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>a.x : Symbol(x, Decl(satisfiesScenarios.ts, 96, 15)) +>a : Symbol(a, Decl(satisfiesScenarios.ts, 96, 9)) +>x : Symbol(x, Decl(satisfiesScenarios.ts, 96, 15)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + // Should error + let p = a.y; +>p : Symbol(p, Decl(satisfiesScenarios.ts, 100, 7)) +>a : Symbol(a, Decl(satisfiesScenarios.ts, 96, 9)) +} + +namespace ContextualTyping { +>ContextualTyping : Symbol(ContextualTyping, Decl(satisfiesScenarios.ts, 101, 1)) + + type Predicates = { [s: string]: (n: number) => boolean }; +>Predicates : Symbol(Predicates, Decl(satisfiesScenarios.ts, 103, 28)) +>s : Symbol(s, Decl(satisfiesScenarios.ts, 104, 25)) +>n : Symbol(n, Decl(satisfiesScenarios.ts, 104, 38)) + + const p: Predicates = { +>p : Symbol(p, Decl(satisfiesScenarios.ts, 106, 9)) +>Predicates : Symbol(Predicates, Decl(satisfiesScenarios.ts, 103, 28)) + + isEven: n => n % 2 === 0, +>isEven : Symbol(isEven, Decl(satisfiesScenarios.ts, 106, 27)) +>n : Symbol(n, Decl(satisfiesScenarios.ts, 107, 15)) +>n : Symbol(n, Decl(satisfiesScenarios.ts, 107, 15)) + + isOdd: n => n % 2 === 1 +>isOdd : Symbol(isOdd, Decl(satisfiesScenarios.ts, 107, 33)) +>n : Symbol(n, Decl(satisfiesScenarios.ts, 108, 14)) +>n : Symbol(n, Decl(satisfiesScenarios.ts, 108, 14)) + + }; +} diff --git a/tests/baselines/reference/satisfiesScenarios.types b/tests/baselines/reference/satisfiesScenarios.types new file mode 100644 index 0000000000000..dc34573da51b9 --- /dev/null +++ b/tests/baselines/reference/satisfiesScenarios.types @@ -0,0 +1,363 @@ +=== tests/cases/compiler/satisfiesScenarios.ts === +const x = [1, 2] satisfies [number, number]; +>x : [number, number] +>[1, 2] satisfies [number, number] : [number, number] +>[1, 2] : [number, number] +>1 : 1 +>2 : 2 + +interface A { + a: string +>a : string +} +let d = { a: 'test' } satisfies A; +>d : { a: string; } +>{ a: 'test' } satisfies A : { a: string; } +>{ a: 'test' } : { a: string; } +>a : string +>'test' : "test" + +let e = { a: 'test', b: 'test' } satisfies A; +>e : { a: string; b: string; } +>{ a: 'test', b: 'test' } satisfies A : { a: string; b: string; } +>{ a: 'test', b: 'test' } : { a: string; b: string; } +>a : string +>'test' : "test" +>b : string +>'test' : "test" + +// Most examples from #47920 +namespace PropNameConstraining { +>PropNameConstraining : typeof PropNameConstraining + + type Keys = 'a' | 'b' | 'c' | 'd'; +>Keys : Keys + + const p = { +>p : { a: number; b: string; x: number; } +>{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys' } satisfies Partial> : { a: number; b: string; x: number; } +>{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys' } : { a: number; b: string; x: number; } + + a: 0, +>a : number +>0 : 0 + + b: "hello", +>b : string +>"hello" : "hello" + + x: 8 // Should error, 'x' isn't in 'Keys' +>x : number +>8 : 8 + + } satisfies Partial>; + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); +>a : string +>p.a.toFixed() : string +>p.a.toFixed : (fractionDigits?: number) => string +>p.a : number +>p : { a: number; b: string; x: number; } +>a : number +>toFixed : (fractionDigits?: number) => string + + let b = p.b.substring(1); +>b : string +>p.b.substring(1) : string +>p.b.substring : (start: number, end?: number) => string +>p.b : string +>p : { a: number; b: string; x: number; } +>b : string +>substring : (start: number, end?: number) => string +>1 : 1 + + // Should error even though 'd' is in 'Keys' + let d = p.d; +>d : any +>p.d : any +>p : { a: number; b: string; x: number; } +>d : any +} + +namespace PropertyNameFulfillment { +>PropertyNameFulfillment : typeof PropertyNameFulfillment + + type Keys = 'a' | 'b' | 'c' | 'd'; +>Keys : Keys + + const p = { +>p : { a: number; b: string; x: number; } +>{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys' } satisfies Record : { a: number; b: string; x: number; } +>{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys' } : { a: number; b: string; x: number; } + + a: 0, +>a : number +>0 : 0 + + b: "hello", +>b : string +>"hello" : "hello" + + x: 8 // Should error, 'x' isn't in 'Keys' +>x : number +>8 : 8 + + } satisfies Record; + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); +>a : string +>p.a.toFixed() : string +>p.a.toFixed : (fractionDigits?: number) => string +>p.a : number +>p : { a: number; b: string; x: number; } +>a : number +>toFixed : (fractionDigits?: number) => string + + let b = p.b.substr(1); +>b : string +>p.b.substr(1) : string +>p.b.substr : (from: number, length?: number) => string +>p.b : string +>p : { a: number; b: string; x: number; } +>b : string +>substr : (from: number, length?: number) => string +>1 : 1 + + // Should error even though 'd' is in 'Keys' + let d = p.d; +>d : any +>p.d : any +>p : { a: number; b: string; x: number; } +>d : any +} + +namespace PropertyValueConformance { +>PropertyValueConformance : typeof PropertyValueConformance + + type Facts = { [key: string]: boolean }; +>Facts : Facts +>key : string + + declare function checkTruths(x: Facts): void; +>checkTruths : (x: Facts) => void +>x : Facts + + declare function checkM(x: { m: boolean }): void; +>checkM : (x: { m: boolean;}) => void +>x : { m: boolean; } +>m : boolean + + const x = { +>x : { m: boolean; } +>{ m: true } : { m: boolean; } + + m: true +>m : boolean +>true : true + + }; + + // Should be OK + checkTruths(x); +>checkTruths(x) : void +>checkTruths : (x: Facts) => void +>x : { m: boolean; } + + // Should be OK + checkM(x); +>checkM(x) : void +>checkM : (x: { m: boolean; }) => void +>x : { m: boolean; } + + // Should fail under --noIndexSignaturePropertyAccess + console.log(x.z); +>console.log(x.z) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>x.z : any +>x : { m: boolean; } +>z : any + + // Should be OK under --noUncheckedIndexedAccess + const m: boolean = x.m; +>m : boolean +>x.m : boolean +>x : { m: boolean; } +>m : boolean + + // Should be 'm' + type M = keyof typeof x; +>M : "m" +>x : { m: boolean; } + + // Should be able to detect a failure here + const x2 = { +>x2 : { m: true; s: string; } +>{ m: true, s: "false" } satisfies Facts : { m: true; s: string; } +>{ m: true, s: "false" } : { m: true; s: string; } + + m: true, +>m : true +>true : true + + s: "false" +>s : string +>"false" : "false" + + } satisfies Facts; +} + +namespace PropertyValueConformance2 { +>PropertyValueConformance2 : typeof PropertyValueConformance2 + + export type Color = { r: number, g: number, b: number }; +>Color : Color +>r : number +>g : number +>b : number + + // All of these should be Colors, but I only use some of them here. + export const Palette = { +>Palette : { white: { r: number; g: number; b: number; }; black: { r: number; g: number; d: number; }; blue: { r: number; g: number; b: number; }; } +>{ white: { r: 255, g: 255, b: 255 }, black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' blue: { r: 0, g: 0, b: 255 }, } satisfies Record : { white: { r: number; g: number; b: number; }; black: { r: number; g: number; d: number; }; blue: { r: number; g: number; b: number; }; } +>{ white: { r: 255, g: 255, b: 255 }, black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' blue: { r: 0, g: 0, b: 255 }, } : { white: { r: number; g: number; b: number; }; black: { r: number; g: number; d: number; }; blue: { r: number; g: number; b: number; }; } + + white: { r: 255, g: 255, b: 255 }, +>white : { r: number; g: number; b: number; } +>{ r: 255, g: 255, b: 255 } : { r: number; g: number; b: number; } +>r : number +>255 : 255 +>g : number +>255 : 255 +>b : number +>255 : 255 + + black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' +>black : { r: number; g: number; d: number; } +>{ r: 0, g: 0, d: 0 } : { r: number; g: number; d: number; } +>r : number +>0 : 0 +>g : number +>0 : 0 +>d : number +>0 : 0 + + blue: { r: 0, g: 0, b: 255 }, +>blue : { r: number; g: number; b: number; } +>{ r: 0, g: 0, b: 255 } : { r: number; g: number; b: number; } +>r : number +>0 : 0 +>g : number +>0 : 0 +>b : number +>255 : 255 + + } satisfies Record; +} + +namespace EnsureInterfaceImpl { +>EnsureInterfaceImpl : typeof EnsureInterfaceImpl + + type Movable = { +>Movable : Movable + + move(distance: number): void; +>move : (distance: number) => void +>distance : number + + }; + + const car = { +>car : { start(): void; move(d: number): void; stop(): void; } +>{ start() { }, move(d) { // d should be number }, stop() { } } satisfies Movable & Record : { start(): void; move(d: number): void; stop(): void; } +>{ start() { }, move(d) { // d should be number }, stop() { } } : { start(): void; move(d: number): void; stop(): void; } + + start() { }, +>start : () => void + + move(d) { +>move : (d: number) => void +>d : number + + // d should be number + }, + stop() { } +>stop : () => void + + } satisfies Movable & Record; +} + +namespace OptionalMemberConformance { +>OptionalMemberConformance : typeof OptionalMemberConformance + + type Point2d = { x: number, y: number }; +>Point2d : Point2d +>x : number +>y : number + + // Undesirable behavior today with type annotation + const a = { x: 10 } satisfies Partial; +>a : { x: number; } +>{ x: 10 } satisfies Partial : { x: number; } +>{ x: 10 } : { x: number; } +>x : number +>10 : 10 + + // Should OK + console.log(a.x.toFixed()); +>console.log(a.x.toFixed()) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>a.x.toFixed() : string +>a.x.toFixed : (fractionDigits?: number) => string +>a.x : number +>a : { x: number; } +>x : number +>toFixed : (fractionDigits?: number) => string + + // Should error + let p = a.y; +>p : any +>a.y : any +>a : { x: number; } +>y : any +} + +namespace ContextualTyping { +>ContextualTyping : typeof ContextualTyping + + type Predicates = { [s: string]: (n: number) => boolean }; +>Predicates : Predicates +>s : string +>n : number + + const p: Predicates = { +>p : Predicates +>{ isEven: n => n % 2 === 0, isOdd: n => n % 2 === 1 } : { isEven: (n: number) => boolean; isOdd: (n: number) => boolean; } + + isEven: n => n % 2 === 0, +>isEven : (n: number) => boolean +>n => n % 2 === 0 : (n: number) => boolean +>n : number +>n % 2 === 0 : boolean +>n % 2 : number +>n : number +>2 : 2 +>0 : 0 + + isOdd: n => n % 2 === 1 +>isOdd : (n: number) => boolean +>n => n % 2 === 1 : (n: number) => boolean +>n : number +>n % 2 === 1 : boolean +>n % 2 : number +>n : number +>2 : 2 +>1 : 1 + + }; +} diff --git a/tests/cases/compiler/satisfiesScenarios.ts b/tests/cases/compiler/satisfiesScenarios.ts new file mode 100644 index 0000000000000..44f145e87af5b --- /dev/null +++ b/tests/cases/compiler/satisfiesScenarios.ts @@ -0,0 +1,112 @@ + +const x = [1, 2] satisfies [number, number]; + +interface A { + a: string +} +let d = { a: 'test' } satisfies A; +let e = { a: 'test', b: 'test' } satisfies A; + +// Most examples from #47920 +namespace PropNameConstraining { + type Keys = 'a' | 'b' | 'c' | 'd'; + + const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' + } satisfies Partial>; + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); + let b = p.b.substring(1); + // Should error even though 'd' is in 'Keys' + let d = p.d; +} + +namespace PropertyNameFulfillment { + type Keys = 'a' | 'b' | 'c' | 'd'; + + const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' + } satisfies Record; + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); + let b = p.b.substr(1); + // Should error even though 'd' is in 'Keys' + let d = p.d; +} + +namespace PropertyValueConformance { + type Facts = { [key: string]: boolean }; + declare function checkTruths(x: Facts): void; + declare function checkM(x: { m: boolean }): void; + const x = { + m: true + }; + + // Should be OK + checkTruths(x); + // Should be OK + checkM(x); + // Should fail under --noIndexSignaturePropertyAccess + console.log(x.z); + // Should be OK under --noUncheckedIndexedAccess + const m: boolean = x.m; + + // Should be 'm' + type M = keyof typeof x; + + // Should be able to detect a failure here + const x2 = { + m: true, + s: "false" + } satisfies Facts; +} + +namespace PropertyValueConformance2 { + export type Color = { r: number, g: number, b: number }; + + // All of these should be Colors, but I only use some of them here. + export const Palette = { + white: { r: 255, g: 255, b: 255 }, + black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' + blue: { r: 0, g: 0, b: 255 }, + } satisfies Record; +} + +namespace EnsureInterfaceImpl { + type Movable = { + move(distance: number): void; + }; + + const car = { + start() { }, + move(d) { + // d should be number + }, + stop() { } + } satisfies Movable & Record; +} + +namespace OptionalMemberConformance { + type Point2d = { x: number, y: number }; + // Undesirable behavior today with type annotation + const a = { x: 10 } satisfies Partial; + // Should OK + console.log(a.x.toFixed()); + // Should error + let p = a.y; +} + +namespace ContextualTyping { + type Predicates = { [s: string]: (n: number) => boolean }; + + const p: Predicates = { + isEven: n => n % 2 === 0, + isOdd: n => n % 2 === 1 + }; +} \ No newline at end of file From 95983bdfda6c12043dccbdc83aad44cce66167a4 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Wed, 23 Mar 2022 21:58:34 +0200 Subject: [PATCH 06/11] remove isExpression in favor of using type casting --- src/compiler/checker.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dcee31356397d..9da3d0bf44649 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27015,11 +27015,8 @@ namespace ts { return getContextualType(parent as NonNullExpression, contextFlags); case SyntaxKind.SatisfiesExpression: const assertedType = getTypeFromTypeNode((parent as SatisfiesExpression).type); - const outerType = isExpression(parent) ? getContextualType(parent) : undefined; - if (outerType !== undefined) { - return getIntersectionType([assertedType, outerType]); - } - return assertedType; + const outerType = getContextualType(parent as SatisfiesExpression); + return outerType === undefined ? assertedType : getIntersectionType([assertedType, outerType]); case SyntaxKind.ExportAssignment: return tryGetTypeFromEffectiveTypeNode(parent as ExportAssignment); case SyntaxKind.JsxExpression: From a9050e5ad327fbc62d39e93567f8bb20d18d54ba Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Wed, 23 Mar 2022 23:45:44 +0200 Subject: [PATCH 07/11] move tests from compiler to conformance folder --- src/testRunner/compilerRunner.ts | 4 +- .../reference/satisfiesContextualType.symbols | 27 -- .../reference/satisfiesScenarios.errors.txt | 150 -------- .../baselines/reference/satisfiesScenarios.js | 198 ---------- .../reference/satisfiesScenarios.symbols | 305 --------------- .../reference/satisfiesScenarios.types | 363 ------------------ .../reference/typeSatisfaction.errors.txt | 25 +- tests/baselines/reference/typeSatisfaction.js | 31 +- .../reference/typeSatisfaction.symbols | 40 +- .../reference/typeSatisfaction.types | 47 ++- .../typeSatisfaction_contextualTyping1.js | 14 + ...typeSatisfaction_contextualTyping1.symbols | 22 ++ .../typeSatisfaction_contextualTyping1.types | 33 ++ ... => typeSatisfaction_contextualTyping2.js} | 4 +- ...typeSatisfaction_contextualTyping2.symbols | 27 ++ ... typeSatisfaction_contextualTyping2.types} | 2 +- .../typeSatisfaction_ensureInterfaceImpl.js | 22 ++ ...peSatisfaction_ensureInterfaceImpl.symbols | 29 ++ ...typeSatisfaction_ensureInterfaceImpl.types | 29 ++ ...ors.txt => typeSatisfaction_js.errors.txt} | 0 ...Satisfaction.js => typeSatisfaction_js.js} | 0 ...on.symbols => typeSatisfaction_js.symbols} | 0 ...action.types => typeSatisfaction_js.types} | 0 ...ction_optionalMemberConformance.errors.txt | 14 + ...eSatisfaction_optionalMemberConformance.js | 17 + ...sfaction_optionalMemberConformance.symbols | 29 ++ ...tisfaction_optionalMemberConformance.types | 34 ++ ...tisfaction_propNameConstraining.errors.txt | 25 ++ .../typeSatisfaction_propNameConstraining.js | 27 ++ ...eSatisfaction_propNameConstraining.symbols | 43 +++ ...ypeSatisfaction_propNameConstraining.types | 50 +++ ...faction_propertyNameFulfillment.errors.txt | 25 ++ ...ypeSatisfaction_propertyNameFulfillment.js | 27 ++ ...tisfaction_propertyNameFulfillment.symbols | 42 ++ ...Satisfaction_propertyNameFulfillment.types | 50 +++ ...accessfromindexsignature=false).errors.txt | 34 ++ ...propertyaccessfromindexsignature=false).js | 42 ++ ...rtyaccessfromindexsignature=false).symbols | 64 +++ ...pertyaccessfromindexsignature=false).types | 73 ++++ ...yaccessfromindexsignature=true).errors.txt | 34 ++ ...opropertyaccessfromindexsignature=true).js | 42 ++ ...ertyaccessfromindexsignature=true).symbols | 64 +++ ...opertyaccessfromindexsignature=true).types | 73 ++++ ...nouncheckedindexedaccess=false).errors.txt | 34 ++ ...rmance2(nouncheckedindexedaccess=false).js | 42 ++ ...e2(nouncheckedindexedaccess=false).symbols | 64 +++ ...nce2(nouncheckedindexedaccess=false).types | 73 ++++ ...(nouncheckedindexedaccess=true).errors.txt | 34 ++ ...ormance2(nouncheckedindexedaccess=true).js | 42 ++ ...ce2(nouncheckedindexedaccess=true).symbols | 64 +++ ...ance2(nouncheckedindexedaccess=true).types | 73 ++++ ...ction_propertyValueConformance3.errors.txt | 17 + ...eSatisfaction_propertyValueConformance3.js | 21 + ...sfaction_propertyValueConformance3.symbols | 33 ++ ...tisfaction_propertyValueConformance3.types | 45 +++ ...usIntersectionOfContextualTypes.errors.txt | 20 + ...on_vacuousIntersectionOfContextualTypes.js | 8 + ...cuousIntersectionOfContextualTypes.symbols | 10 + ...vacuousIntersectionOfContextualTypes.types | 15 + tests/cases/compiler/satisfiesScenarios.ts | 112 ------ .../typeSatisfaction/typeSatisfaction.ts | 18 +- .../typeSatisfaction_contextualTyping1.ts | 6 + .../typeSatisfaction_contextualTyping2.ts} | 18 +- .../typeSatisfaction_ensureInterfaceImpl.ts | 11 + .../typeSatisfaction/typeSatisfaction_js.ts} | 10 +- ...eSatisfaction_optionalMemberConformance.ts | 7 + .../typeSatisfaction_propNameConstraining.ts | 13 + ...ypeSatisfaction_propertyNameFulfillment.ts | 13 + ...eSatisfaction_propertyValueConformance1.ts | 25 ++ ...eSatisfaction_propertyValueConformance2.ts | 25 ++ ...eSatisfaction_propertyValueConformance3.ts | 8 + ...on_vacuousIntersectionOfContextualTypes.ts | 2 + 72 files changed, 1830 insertions(+), 1214 deletions(-) delete mode 100644 tests/baselines/reference/satisfiesContextualType.symbols delete mode 100644 tests/baselines/reference/satisfiesScenarios.errors.txt delete mode 100644 tests/baselines/reference/satisfiesScenarios.js delete mode 100644 tests/baselines/reference/satisfiesScenarios.symbols delete mode 100644 tests/baselines/reference/satisfiesScenarios.types create mode 100644 tests/baselines/reference/typeSatisfaction_contextualTyping1.js create mode 100644 tests/baselines/reference/typeSatisfaction_contextualTyping1.symbols create mode 100644 tests/baselines/reference/typeSatisfaction_contextualTyping1.types rename tests/baselines/reference/{satisfiesContextualType.js => typeSatisfaction_contextualTyping2.js} (81%) create mode 100644 tests/baselines/reference/typeSatisfaction_contextualTyping2.symbols rename tests/baselines/reference/{satisfiesContextualType.types => typeSatisfaction_contextualTyping2.types} (88%) create mode 100644 tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.js create mode 100644 tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.symbols create mode 100644 tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.types rename tests/baselines/reference/{jsFileCompilationTypeSatisfaction.errors.txt => typeSatisfaction_js.errors.txt} (100%) rename tests/baselines/reference/{jsFileCompilationTypeSatisfaction.js => typeSatisfaction_js.js} (100%) rename tests/baselines/reference/{jsFileCompilationTypeSatisfaction.symbols => typeSatisfaction_js.symbols} (100%) rename tests/baselines/reference/{jsFileCompilationTypeSatisfaction.types => typeSatisfaction_js.types} (100%) create mode 100644 tests/baselines/reference/typeSatisfaction_optionalMemberConformance.errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction_optionalMemberConformance.js create mode 100644 tests/baselines/reference/typeSatisfaction_optionalMemberConformance.symbols create mode 100644 tests/baselines/reference/typeSatisfaction_optionalMemberConformance.types create mode 100644 tests/baselines/reference/typeSatisfaction_propNameConstraining.errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction_propNameConstraining.js create mode 100644 tests/baselines/reference/typeSatisfaction_propNameConstraining.symbols create mode 100644 tests/baselines/reference/typeSatisfaction_propNameConstraining.types create mode 100644 tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.js create mode 100644 tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.symbols create mode 100644 tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.types create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).js create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).symbols create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).types create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).js create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).symbols create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).types create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).js create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).symbols create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).types create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).js create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).symbols create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).types create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance3.errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance3.js create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance3.symbols create mode 100644 tests/baselines/reference/typeSatisfaction_propertyValueConformance3.types create mode 100644 tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.js create mode 100644 tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.symbols create mode 100644 tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.types delete mode 100644 tests/cases/compiler/satisfiesScenarios.ts create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping1.ts rename tests/cases/{compiler/satisfiesContextualType.ts => conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping2.ts} (97%) create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_ensureInterfaceImpl.ts rename tests/cases/{compiler/jsFileCompilationTypeSatisfaction.ts => conformance/expressions/typeSatisfaction/typeSatisfaction_js.ts} (94%) create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_optionalMemberConformance.ts create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propNameConstraining.ts create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyNameFulfillment.ts create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance3.ts create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index 1d320d667cf5f..7967bf1afc402 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -141,7 +141,9 @@ namespace Harness { "preserveConstEnums", "skipLibCheck", "exactOptionalPropertyTypes", - "useUnknownInCatchVariables" + "useUnknownInCatchVariables", + "noUncheckedIndexedAccess", + "noPropertyAccessFromIndexSignature" ]; private fileName: string; private justName: string; diff --git a/tests/baselines/reference/satisfiesContextualType.symbols b/tests/baselines/reference/satisfiesContextualType.symbols deleted file mode 100644 index 1dd96046d890d..0000000000000 --- a/tests/baselines/reference/satisfiesContextualType.symbols +++ /dev/null @@ -1,27 +0,0 @@ -=== tests/cases/compiler/satisfiesContextualType.ts === -let obj: { f(s: string): void } & Record = { ->obj : Symbol(obj, Decl(satisfiesContextualType.ts, 0, 3)) ->f : Symbol(f, Decl(satisfiesContextualType.ts, 0, 10)) ->s : Symbol(s, Decl(satisfiesContextualType.ts, 0, 13)) ->Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) - - f(s) { }, // "incorrect" implicit any on 's' ->f : Symbol(f, Decl(satisfiesContextualType.ts, 0, 61)) ->s : Symbol(s, Decl(satisfiesContextualType.ts, 1, 6)) - - g(s) { } ->g : Symbol(g, Decl(satisfiesContextualType.ts, 1, 13)) ->s : Symbol(s, Decl(satisfiesContextualType.ts, 2, 6)) - -} satisfies { g(s: string): void } & Record; ->g : Symbol(g, Decl(satisfiesContextualType.ts, 3, 13)) ->s : Symbol(s, Decl(satisfiesContextualType.ts, 3, 16)) ->Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) - -// This needs to not crash (outer node is not expression) -({ f(x) { } }) satisfies { f(s: string): void }; ->f : Symbol(f, Decl(satisfiesContextualType.ts, 6, 2)) ->x : Symbol(x, Decl(satisfiesContextualType.ts, 6, 5)) ->f : Symbol(f, Decl(satisfiesContextualType.ts, 6, 26)) ->s : Symbol(s, Decl(satisfiesContextualType.ts, 6, 29)) - diff --git a/tests/baselines/reference/satisfiesScenarios.errors.txt b/tests/baselines/reference/satisfiesScenarios.errors.txt deleted file mode 100644 index ea637b3467df2..0000000000000 --- a/tests/baselines/reference/satisfiesScenarios.errors.txt +++ /dev/null @@ -1,150 +0,0 @@ -tests/cases/compiler/satisfiesScenarios.ts(7,22): error TS1360: Type '{ a: string; b: string; }' does not satisfy the expected type 'A'. - Object literal may only specify known properties, and 'b' does not exist in type 'A'. -tests/cases/compiler/satisfiesScenarios.ts(16,9): error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Partial>'. - Object literal may only specify known properties, and 'x' does not exist in type 'Partial>'. -tests/cases/compiler/satisfiesScenarios.ts(23,15): error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. -tests/cases/compiler/satisfiesScenarios.ts(32,9): error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Record'. - Object literal may only specify known properties, and 'x' does not exist in type 'Record'. -tests/cases/compiler/satisfiesScenarios.ts(39,15): error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. -tests/cases/compiler/satisfiesScenarios.ts(55,19): error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. -tests/cases/compiler/satisfiesScenarios.ts(65,9): error TS2322: Type 'string' is not assignable to type 'boolean'. -tests/cases/compiler/satisfiesScenarios.ts(75,30): error TS2322: Type '{ r: number; g: number; d: number; }' is not assignable to type 'Color'. - Object literal may only specify known properties, and 'd' does not exist in type 'Color'. -tests/cases/compiler/satisfiesScenarios.ts(101,15): error TS2339: Property 'y' does not exist on type '{ x: number; }'. - - -==== tests/cases/compiler/satisfiesScenarios.ts (9 errors) ==== - const x = [1, 2] satisfies [number, number]; - - interface A { - a: string - } - let d = { a: 'test' } satisfies A; - let e = { a: 'test', b: 'test' } satisfies A; - ~~~~~~~~~ -!!! error TS1360: Type '{ a: string; b: string; }' does not satisfy the expected type 'A'. -!!! error TS1360: Object literal may only specify known properties, and 'b' does not exist in type 'A'. - - // Most examples from #47920 - namespace PropNameConstraining { - type Keys = 'a' | 'b' | 'c' | 'd'; - - const p = { - a: 0, - b: "hello", - x: 8 // Should error, 'x' isn't in 'Keys' - ~~~~ -!!! error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Partial>'. -!!! error TS1360: Object literal may only specify known properties, and 'x' does not exist in type 'Partial>'. - } satisfies Partial>; - - // Should be OK -- retain info that a is number and b is string - let a = p.a.toFixed(); - let b = p.b.substring(1); - // Should error even though 'd' is in 'Keys' - let d = p.d; - ~ -!!! error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. - } - - namespace PropertyNameFulfillment { - type Keys = 'a' | 'b' | 'c' | 'd'; - - const p = { - a: 0, - b: "hello", - x: 8 // Should error, 'x' isn't in 'Keys' - ~~~~ -!!! error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Record'. -!!! error TS1360: Object literal may only specify known properties, and 'x' does not exist in type 'Record'. - } satisfies Record; - - // Should be OK -- retain info that a is number and b is string - let a = p.a.toFixed(); - let b = p.b.substr(1); - // Should error even though 'd' is in 'Keys' - let d = p.d; - ~ -!!! error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. - } - - namespace PropertyValueConformance { - type Facts = { [key: string]: boolean }; - declare function checkTruths(x: Facts): void; - declare function checkM(x: { m: boolean }): void; - const x = { - m: true - }; - - // Should be OK - checkTruths(x); - // Should be OK - checkM(x); - // Should fail under --noIndexSignaturePropertyAccess - console.log(x.z); - ~ -!!! error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. - // Should be OK under --noUncheckedIndexedAccess - const m: boolean = x.m; - - // Should be 'm' - type M = keyof typeof x; - - // Should be able to detect a failure here - const x2 = { - m: true, - s: "false" - ~ -!!! error TS2322: Type 'string' is not assignable to type 'boolean'. -!!! related TS6501 tests/cases/compiler/satisfiesScenarios.ts:43:20: The expected type comes from this index signature. - } satisfies Facts; - } - - namespace PropertyValueConformance2 { - export type Color = { r: number, g: number, b: number }; - - // All of these should be Colors, but I only use some of them here. - export const Palette = { - white: { r: 255, g: 255, b: 255 }, - black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' - ~~~~ -!!! error TS2322: Type '{ r: number; g: number; d: number; }' is not assignable to type 'Color'. -!!! error TS2322: Object literal may only specify known properties, and 'd' does not exist in type 'Color'. - blue: { r: 0, g: 0, b: 255 }, - } satisfies Record; - } - - namespace EnsureInterfaceImpl { - type Movable = { - move(distance: number): void; - }; - - const car = { - start() { }, - move(d) { - // d should be number - }, - stop() { } - } satisfies Movable & Record; - } - - namespace OptionalMemberConformance { - type Point2d = { x: number, y: number }; - // Undesirable behavior today with type annotation - const a = { x: 10 } satisfies Partial; - // Should OK - console.log(a.x.toFixed()); - // Should error - let p = a.y; - ~ -!!! error TS2339: Property 'y' does not exist on type '{ x: number; }'. - } - - namespace ContextualTyping { - type Predicates = { [s: string]: (n: number) => boolean }; - - const p: Predicates = { - isEven: n => n % 2 === 0, - isOdd: n => n % 2 === 1 - }; - } \ No newline at end of file diff --git a/tests/baselines/reference/satisfiesScenarios.js b/tests/baselines/reference/satisfiesScenarios.js deleted file mode 100644 index 2fb613887b277..0000000000000 --- a/tests/baselines/reference/satisfiesScenarios.js +++ /dev/null @@ -1,198 +0,0 @@ -//// [satisfiesScenarios.ts] -const x = [1, 2] satisfies [number, number]; - -interface A { - a: string -} -let d = { a: 'test' } satisfies A; -let e = { a: 'test', b: 'test' } satisfies A; - -// Most examples from #47920 -namespace PropNameConstraining { - type Keys = 'a' | 'b' | 'c' | 'd'; - - const p = { - a: 0, - b: "hello", - x: 8 // Should error, 'x' isn't in 'Keys' - } satisfies Partial>; - - // Should be OK -- retain info that a is number and b is string - let a = p.a.toFixed(); - let b = p.b.substring(1); - // Should error even though 'd' is in 'Keys' - let d = p.d; -} - -namespace PropertyNameFulfillment { - type Keys = 'a' | 'b' | 'c' | 'd'; - - const p = { - a: 0, - b: "hello", - x: 8 // Should error, 'x' isn't in 'Keys' - } satisfies Record; - - // Should be OK -- retain info that a is number and b is string - let a = p.a.toFixed(); - let b = p.b.substr(1); - // Should error even though 'd' is in 'Keys' - let d = p.d; -} - -namespace PropertyValueConformance { - type Facts = { [key: string]: boolean }; - declare function checkTruths(x: Facts): void; - declare function checkM(x: { m: boolean }): void; - const x = { - m: true - }; - - // Should be OK - checkTruths(x); - // Should be OK - checkM(x); - // Should fail under --noIndexSignaturePropertyAccess - console.log(x.z); - // Should be OK under --noUncheckedIndexedAccess - const m: boolean = x.m; - - // Should be 'm' - type M = keyof typeof x; - - // Should be able to detect a failure here - const x2 = { - m: true, - s: "false" - } satisfies Facts; -} - -namespace PropertyValueConformance2 { - export type Color = { r: number, g: number, b: number }; - - // All of these should be Colors, but I only use some of them here. - export const Palette = { - white: { r: 255, g: 255, b: 255 }, - black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' - blue: { r: 0, g: 0, b: 255 }, - } satisfies Record; -} - -namespace EnsureInterfaceImpl { - type Movable = { - move(distance: number): void; - }; - - const car = { - start() { }, - move(d) { - // d should be number - }, - stop() { } - } satisfies Movable & Record; -} - -namespace OptionalMemberConformance { - type Point2d = { x: number, y: number }; - // Undesirable behavior today with type annotation - const a = { x: 10 } satisfies Partial; - // Should OK - console.log(a.x.toFixed()); - // Should error - let p = a.y; -} - -namespace ContextualTyping { - type Predicates = { [s: string]: (n: number) => boolean }; - - const p: Predicates = { - isEven: n => n % 2 === 0, - isOdd: n => n % 2 === 1 - }; -} - -//// [satisfiesScenarios.js] -var x = [1, 2]; -var d = { a: 'test' }; -var e = { a: 'test', b: 'test' }; -// Most examples from #47920 -var PropNameConstraining; -(function (PropNameConstraining) { - var p = { - a: 0, - b: "hello", - x: 8 // Should error, 'x' isn't in 'Keys' - }; - // Should be OK -- retain info that a is number and b is string - var a = p.a.toFixed(); - var b = p.b.substring(1); - // Should error even though 'd' is in 'Keys' - var d = p.d; -})(PropNameConstraining || (PropNameConstraining = {})); -var PropertyNameFulfillment; -(function (PropertyNameFulfillment) { - var p = { - a: 0, - b: "hello", - x: 8 // Should error, 'x' isn't in 'Keys' - }; - // Should be OK -- retain info that a is number and b is string - var a = p.a.toFixed(); - var b = p.b.substr(1); - // Should error even though 'd' is in 'Keys' - var d = p.d; -})(PropertyNameFulfillment || (PropertyNameFulfillment = {})); -var PropertyValueConformance; -(function (PropertyValueConformance) { - var x = { - m: true - }; - // Should be OK - checkTruths(x); - // Should be OK - checkM(x); - // Should fail under --noIndexSignaturePropertyAccess - console.log(x.z); - // Should be OK under --noUncheckedIndexedAccess - var m = x.m; - // Should be able to detect a failure here - var x2 = { - m: true, - s: "false" - }; -})(PropertyValueConformance || (PropertyValueConformance = {})); -var PropertyValueConformance2; -(function (PropertyValueConformance2) { - // All of these should be Colors, but I only use some of them here. - PropertyValueConformance2.Palette = { - white: { r: 255, g: 255, b: 255 }, - black: { r: 0, g: 0, d: 0 }, - blue: { r: 0, g: 0, b: 255 } - }; -})(PropertyValueConformance2 || (PropertyValueConformance2 = {})); -var EnsureInterfaceImpl; -(function (EnsureInterfaceImpl) { - var car = { - start: function () { }, - move: function (d) { - // d should be number - }, - stop: function () { } - }; -})(EnsureInterfaceImpl || (EnsureInterfaceImpl = {})); -var OptionalMemberConformance; -(function (OptionalMemberConformance) { - // Undesirable behavior today with type annotation - var a = { x: 10 }; - // Should OK - console.log(a.x.toFixed()); - // Should error - var p = a.y; -})(OptionalMemberConformance || (OptionalMemberConformance = {})); -var ContextualTyping; -(function (ContextualTyping) { - var p = { - isEven: function (n) { return n % 2 === 0; }, - isOdd: function (n) { return n % 2 === 1; } - }; -})(ContextualTyping || (ContextualTyping = {})); diff --git a/tests/baselines/reference/satisfiesScenarios.symbols b/tests/baselines/reference/satisfiesScenarios.symbols deleted file mode 100644 index 5b71015ee8da3..0000000000000 --- a/tests/baselines/reference/satisfiesScenarios.symbols +++ /dev/null @@ -1,305 +0,0 @@ -=== tests/cases/compiler/satisfiesScenarios.ts === -const x = [1, 2] satisfies [number, number]; ->x : Symbol(x, Decl(satisfiesScenarios.ts, 0, 5)) - -interface A { ->A : Symbol(A, Decl(satisfiesScenarios.ts, 0, 44)) - - a: string ->a : Symbol(A.a, Decl(satisfiesScenarios.ts, 2, 13)) -} -let d = { a: 'test' } satisfies A; ->d : Symbol(d, Decl(satisfiesScenarios.ts, 5, 3)) ->a : Symbol(a, Decl(satisfiesScenarios.ts, 5, 9)) ->A : Symbol(A, Decl(satisfiesScenarios.ts, 0, 44)) - -let e = { a: 'test', b: 'test' } satisfies A; ->e : Symbol(e, Decl(satisfiesScenarios.ts, 6, 3)) ->a : Symbol(a, Decl(satisfiesScenarios.ts, 6, 9)) ->b : Symbol(b, Decl(satisfiesScenarios.ts, 6, 20)) ->A : Symbol(A, Decl(satisfiesScenarios.ts, 0, 44)) - -// Most examples from #47920 -namespace PropNameConstraining { ->PropNameConstraining : Symbol(PropNameConstraining, Decl(satisfiesScenarios.ts, 6, 45)) - - type Keys = 'a' | 'b' | 'c' | 'd'; ->Keys : Symbol(Keys, Decl(satisfiesScenarios.ts, 9, 32)) - - const p = { ->p : Symbol(p, Decl(satisfiesScenarios.ts, 12, 9)) - - a: 0, ->a : Symbol(a, Decl(satisfiesScenarios.ts, 12, 15)) - - b: "hello", ->b : Symbol(b, Decl(satisfiesScenarios.ts, 13, 13)) - - x: 8 // Should error, 'x' isn't in 'Keys' ->x : Symbol(x, Decl(satisfiesScenarios.ts, 14, 19)) - - } satisfies Partial>; ->Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) ->Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->Keys : Symbol(Keys, Decl(satisfiesScenarios.ts, 9, 32)) - - // Should be OK -- retain info that a is number and b is string - let a = p.a.toFixed(); ->a : Symbol(a, Decl(satisfiesScenarios.ts, 19, 7)) ->p.a.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->p.a : Symbol(a, Decl(satisfiesScenarios.ts, 12, 15)) ->p : Symbol(p, Decl(satisfiesScenarios.ts, 12, 9)) ->a : Symbol(a, Decl(satisfiesScenarios.ts, 12, 15)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) - - let b = p.b.substring(1); ->b : Symbol(b, Decl(satisfiesScenarios.ts, 20, 7)) ->p.b.substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) ->p.b : Symbol(b, Decl(satisfiesScenarios.ts, 13, 13)) ->p : Symbol(p, Decl(satisfiesScenarios.ts, 12, 9)) ->b : Symbol(b, Decl(satisfiesScenarios.ts, 13, 13)) ->substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) - - // Should error even though 'd' is in 'Keys' - let d = p.d; ->d : Symbol(d, Decl(satisfiesScenarios.ts, 22, 7)) ->p : Symbol(p, Decl(satisfiesScenarios.ts, 12, 9)) -} - -namespace PropertyNameFulfillment { ->PropertyNameFulfillment : Symbol(PropertyNameFulfillment, Decl(satisfiesScenarios.ts, 23, 1)) - - type Keys = 'a' | 'b' | 'c' | 'd'; ->Keys : Symbol(Keys, Decl(satisfiesScenarios.ts, 25, 35)) - - const p = { ->p : Symbol(p, Decl(satisfiesScenarios.ts, 28, 9)) - - a: 0, ->a : Symbol(a, Decl(satisfiesScenarios.ts, 28, 15)) - - b: "hello", ->b : Symbol(b, Decl(satisfiesScenarios.ts, 29, 13)) - - x: 8 // Should error, 'x' isn't in 'Keys' ->x : Symbol(x, Decl(satisfiesScenarios.ts, 30, 19)) - - } satisfies Record; ->Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->Keys : Symbol(Keys, Decl(satisfiesScenarios.ts, 25, 35)) - - // Should be OK -- retain info that a is number and b is string - let a = p.a.toFixed(); ->a : Symbol(a, Decl(satisfiesScenarios.ts, 35, 7)) ->p.a.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->p.a : Symbol(a, Decl(satisfiesScenarios.ts, 28, 15)) ->p : Symbol(p, Decl(satisfiesScenarios.ts, 28, 9)) ->a : Symbol(a, Decl(satisfiesScenarios.ts, 28, 15)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) - - let b = p.b.substr(1); ->b : Symbol(b, Decl(satisfiesScenarios.ts, 36, 7)) ->p.b.substr : Symbol(String.substr, Decl(lib.es5.d.ts, --, --)) ->p.b : Symbol(b, Decl(satisfiesScenarios.ts, 29, 13)) ->p : Symbol(p, Decl(satisfiesScenarios.ts, 28, 9)) ->b : Symbol(b, Decl(satisfiesScenarios.ts, 29, 13)) ->substr : Symbol(String.substr, Decl(lib.es5.d.ts, --, --)) - - // Should error even though 'd' is in 'Keys' - let d = p.d; ->d : Symbol(d, Decl(satisfiesScenarios.ts, 38, 7)) ->p : Symbol(p, Decl(satisfiesScenarios.ts, 28, 9)) -} - -namespace PropertyValueConformance { ->PropertyValueConformance : Symbol(PropertyValueConformance, Decl(satisfiesScenarios.ts, 39, 1)) - - type Facts = { [key: string]: boolean }; ->Facts : Symbol(Facts, Decl(satisfiesScenarios.ts, 41, 36)) ->key : Symbol(key, Decl(satisfiesScenarios.ts, 42, 20)) - - declare function checkTruths(x: Facts): void; ->checkTruths : Symbol(checkTruths, Decl(satisfiesScenarios.ts, 42, 44)) ->x : Symbol(x, Decl(satisfiesScenarios.ts, 43, 33)) ->Facts : Symbol(Facts, Decl(satisfiesScenarios.ts, 41, 36)) - - declare function checkM(x: { m: boolean }): void; ->checkM : Symbol(checkM, Decl(satisfiesScenarios.ts, 43, 49)) ->x : Symbol(x, Decl(satisfiesScenarios.ts, 44, 28)) ->m : Symbol(m, Decl(satisfiesScenarios.ts, 44, 32)) - - const x = { ->x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) - - m: true ->m : Symbol(m, Decl(satisfiesScenarios.ts, 45, 15)) - - }; - - // Should be OK - checkTruths(x); ->checkTruths : Symbol(checkTruths, Decl(satisfiesScenarios.ts, 42, 44)) ->x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) - - // Should be OK - checkM(x); ->checkM : Symbol(checkM, Decl(satisfiesScenarios.ts, 43, 49)) ->x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) - - // Should fail under --noIndexSignaturePropertyAccess - console.log(x.z); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) - - // Should be OK under --noUncheckedIndexedAccess - const m: boolean = x.m; ->m : Symbol(m, Decl(satisfiesScenarios.ts, 56, 9)) ->x.m : Symbol(m, Decl(satisfiesScenarios.ts, 45, 15)) ->x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) ->m : Symbol(m, Decl(satisfiesScenarios.ts, 45, 15)) - - // Should be 'm' - type M = keyof typeof x; ->M : Symbol(M, Decl(satisfiesScenarios.ts, 56, 27)) ->x : Symbol(x, Decl(satisfiesScenarios.ts, 45, 9)) - - // Should be able to detect a failure here - const x2 = { ->x2 : Symbol(x2, Decl(satisfiesScenarios.ts, 62, 9)) - - m: true, ->m : Symbol(m, Decl(satisfiesScenarios.ts, 62, 16)) - - s: "false" ->s : Symbol(s, Decl(satisfiesScenarios.ts, 63, 16)) - - } satisfies Facts; ->Facts : Symbol(Facts, Decl(satisfiesScenarios.ts, 41, 36)) -} - -namespace PropertyValueConformance2 { ->PropertyValueConformance2 : Symbol(PropertyValueConformance2, Decl(satisfiesScenarios.ts, 66, 1)) - - export type Color = { r: number, g: number, b: number }; ->Color : Symbol(Color, Decl(satisfiesScenarios.ts, 68, 37)) ->r : Symbol(r, Decl(satisfiesScenarios.ts, 69, 25)) ->g : Symbol(g, Decl(satisfiesScenarios.ts, 69, 36)) ->b : Symbol(b, Decl(satisfiesScenarios.ts, 69, 47)) - - // All of these should be Colors, but I only use some of them here. - export const Palette = { ->Palette : Symbol(Palette, Decl(satisfiesScenarios.ts, 72, 16)) - - white: { r: 255, g: 255, b: 255 }, ->white : Symbol(white, Decl(satisfiesScenarios.ts, 72, 28)) ->r : Symbol(r, Decl(satisfiesScenarios.ts, 73, 16)) ->g : Symbol(g, Decl(satisfiesScenarios.ts, 73, 24)) ->b : Symbol(b, Decl(satisfiesScenarios.ts, 73, 32)) - - black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' ->black : Symbol(black, Decl(satisfiesScenarios.ts, 73, 42)) ->r : Symbol(r, Decl(satisfiesScenarios.ts, 74, 16)) ->g : Symbol(g, Decl(satisfiesScenarios.ts, 74, 22)) ->d : Symbol(d, Decl(satisfiesScenarios.ts, 74, 28)) - - blue: { r: 0, g: 0, b: 255 }, ->blue : Symbol(blue, Decl(satisfiesScenarios.ts, 74, 36)) ->r : Symbol(r, Decl(satisfiesScenarios.ts, 75, 15)) ->g : Symbol(g, Decl(satisfiesScenarios.ts, 75, 21)) ->b : Symbol(b, Decl(satisfiesScenarios.ts, 75, 27)) - - } satisfies Record; ->Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->Color : Symbol(Color, Decl(satisfiesScenarios.ts, 68, 37)) -} - -namespace EnsureInterfaceImpl { ->EnsureInterfaceImpl : Symbol(EnsureInterfaceImpl, Decl(satisfiesScenarios.ts, 77, 1)) - - type Movable = { ->Movable : Symbol(Movable, Decl(satisfiesScenarios.ts, 79, 31)) - - move(distance: number): void; ->move : Symbol(move, Decl(satisfiesScenarios.ts, 80, 20)) ->distance : Symbol(distance, Decl(satisfiesScenarios.ts, 81, 13)) - - }; - - const car = { ->car : Symbol(car, Decl(satisfiesScenarios.ts, 84, 9)) - - start() { }, ->start : Symbol(start, Decl(satisfiesScenarios.ts, 84, 17)) - - move(d) { ->move : Symbol(move, Decl(satisfiesScenarios.ts, 85, 20)) ->d : Symbol(d, Decl(satisfiesScenarios.ts, 86, 13)) - - // d should be number - }, - stop() { } ->stop : Symbol(stop, Decl(satisfiesScenarios.ts, 88, 10)) - - } satisfies Movable & Record; ->Movable : Symbol(Movable, Decl(satisfiesScenarios.ts, 79, 31)) ->Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) -} - -namespace OptionalMemberConformance { ->OptionalMemberConformance : Symbol(OptionalMemberConformance, Decl(satisfiesScenarios.ts, 91, 1)) - - type Point2d = { x: number, y: number }; ->Point2d : Symbol(Point2d, Decl(satisfiesScenarios.ts, 93, 37)) ->x : Symbol(x, Decl(satisfiesScenarios.ts, 94, 20)) ->y : Symbol(y, Decl(satisfiesScenarios.ts, 94, 31)) - - // Undesirable behavior today with type annotation - const a = { x: 10 } satisfies Partial; ->a : Symbol(a, Decl(satisfiesScenarios.ts, 96, 9)) ->x : Symbol(x, Decl(satisfiesScenarios.ts, 96, 15)) ->Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) ->Point2d : Symbol(Point2d, Decl(satisfiesScenarios.ts, 93, 37)) - - // Should OK - console.log(a.x.toFixed()); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->a.x.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->a.x : Symbol(x, Decl(satisfiesScenarios.ts, 96, 15)) ->a : Symbol(a, Decl(satisfiesScenarios.ts, 96, 9)) ->x : Symbol(x, Decl(satisfiesScenarios.ts, 96, 15)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) - - // Should error - let p = a.y; ->p : Symbol(p, Decl(satisfiesScenarios.ts, 100, 7)) ->a : Symbol(a, Decl(satisfiesScenarios.ts, 96, 9)) -} - -namespace ContextualTyping { ->ContextualTyping : Symbol(ContextualTyping, Decl(satisfiesScenarios.ts, 101, 1)) - - type Predicates = { [s: string]: (n: number) => boolean }; ->Predicates : Symbol(Predicates, Decl(satisfiesScenarios.ts, 103, 28)) ->s : Symbol(s, Decl(satisfiesScenarios.ts, 104, 25)) ->n : Symbol(n, Decl(satisfiesScenarios.ts, 104, 38)) - - const p: Predicates = { ->p : Symbol(p, Decl(satisfiesScenarios.ts, 106, 9)) ->Predicates : Symbol(Predicates, Decl(satisfiesScenarios.ts, 103, 28)) - - isEven: n => n % 2 === 0, ->isEven : Symbol(isEven, Decl(satisfiesScenarios.ts, 106, 27)) ->n : Symbol(n, Decl(satisfiesScenarios.ts, 107, 15)) ->n : Symbol(n, Decl(satisfiesScenarios.ts, 107, 15)) - - isOdd: n => n % 2 === 1 ->isOdd : Symbol(isOdd, Decl(satisfiesScenarios.ts, 107, 33)) ->n : Symbol(n, Decl(satisfiesScenarios.ts, 108, 14)) ->n : Symbol(n, Decl(satisfiesScenarios.ts, 108, 14)) - - }; -} diff --git a/tests/baselines/reference/satisfiesScenarios.types b/tests/baselines/reference/satisfiesScenarios.types deleted file mode 100644 index dc34573da51b9..0000000000000 --- a/tests/baselines/reference/satisfiesScenarios.types +++ /dev/null @@ -1,363 +0,0 @@ -=== tests/cases/compiler/satisfiesScenarios.ts === -const x = [1, 2] satisfies [number, number]; ->x : [number, number] ->[1, 2] satisfies [number, number] : [number, number] ->[1, 2] : [number, number] ->1 : 1 ->2 : 2 - -interface A { - a: string ->a : string -} -let d = { a: 'test' } satisfies A; ->d : { a: string; } ->{ a: 'test' } satisfies A : { a: string; } ->{ a: 'test' } : { a: string; } ->a : string ->'test' : "test" - -let e = { a: 'test', b: 'test' } satisfies A; ->e : { a: string; b: string; } ->{ a: 'test', b: 'test' } satisfies A : { a: string; b: string; } ->{ a: 'test', b: 'test' } : { a: string; b: string; } ->a : string ->'test' : "test" ->b : string ->'test' : "test" - -// Most examples from #47920 -namespace PropNameConstraining { ->PropNameConstraining : typeof PropNameConstraining - - type Keys = 'a' | 'b' | 'c' | 'd'; ->Keys : Keys - - const p = { ->p : { a: number; b: string; x: number; } ->{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys' } satisfies Partial> : { a: number; b: string; x: number; } ->{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys' } : { a: number; b: string; x: number; } - - a: 0, ->a : number ->0 : 0 - - b: "hello", ->b : string ->"hello" : "hello" - - x: 8 // Should error, 'x' isn't in 'Keys' ->x : number ->8 : 8 - - } satisfies Partial>; - - // Should be OK -- retain info that a is number and b is string - let a = p.a.toFixed(); ->a : string ->p.a.toFixed() : string ->p.a.toFixed : (fractionDigits?: number) => string ->p.a : number ->p : { a: number; b: string; x: number; } ->a : number ->toFixed : (fractionDigits?: number) => string - - let b = p.b.substring(1); ->b : string ->p.b.substring(1) : string ->p.b.substring : (start: number, end?: number) => string ->p.b : string ->p : { a: number; b: string; x: number; } ->b : string ->substring : (start: number, end?: number) => string ->1 : 1 - - // Should error even though 'd' is in 'Keys' - let d = p.d; ->d : any ->p.d : any ->p : { a: number; b: string; x: number; } ->d : any -} - -namespace PropertyNameFulfillment { ->PropertyNameFulfillment : typeof PropertyNameFulfillment - - type Keys = 'a' | 'b' | 'c' | 'd'; ->Keys : Keys - - const p = { ->p : { a: number; b: string; x: number; } ->{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys' } satisfies Record : { a: number; b: string; x: number; } ->{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys' } : { a: number; b: string; x: number; } - - a: 0, ->a : number ->0 : 0 - - b: "hello", ->b : string ->"hello" : "hello" - - x: 8 // Should error, 'x' isn't in 'Keys' ->x : number ->8 : 8 - - } satisfies Record; - - // Should be OK -- retain info that a is number and b is string - let a = p.a.toFixed(); ->a : string ->p.a.toFixed() : string ->p.a.toFixed : (fractionDigits?: number) => string ->p.a : number ->p : { a: number; b: string; x: number; } ->a : number ->toFixed : (fractionDigits?: number) => string - - let b = p.b.substr(1); ->b : string ->p.b.substr(1) : string ->p.b.substr : (from: number, length?: number) => string ->p.b : string ->p : { a: number; b: string; x: number; } ->b : string ->substr : (from: number, length?: number) => string ->1 : 1 - - // Should error even though 'd' is in 'Keys' - let d = p.d; ->d : any ->p.d : any ->p : { a: number; b: string; x: number; } ->d : any -} - -namespace PropertyValueConformance { ->PropertyValueConformance : typeof PropertyValueConformance - - type Facts = { [key: string]: boolean }; ->Facts : Facts ->key : string - - declare function checkTruths(x: Facts): void; ->checkTruths : (x: Facts) => void ->x : Facts - - declare function checkM(x: { m: boolean }): void; ->checkM : (x: { m: boolean;}) => void ->x : { m: boolean; } ->m : boolean - - const x = { ->x : { m: boolean; } ->{ m: true } : { m: boolean; } - - m: true ->m : boolean ->true : true - - }; - - // Should be OK - checkTruths(x); ->checkTruths(x) : void ->checkTruths : (x: Facts) => void ->x : { m: boolean; } - - // Should be OK - checkM(x); ->checkM(x) : void ->checkM : (x: { m: boolean; }) => void ->x : { m: boolean; } - - // Should fail under --noIndexSignaturePropertyAccess - console.log(x.z); ->console.log(x.z) : void ->console.log : (...data: any[]) => void ->console : Console ->log : (...data: any[]) => void ->x.z : any ->x : { m: boolean; } ->z : any - - // Should be OK under --noUncheckedIndexedAccess - const m: boolean = x.m; ->m : boolean ->x.m : boolean ->x : { m: boolean; } ->m : boolean - - // Should be 'm' - type M = keyof typeof x; ->M : "m" ->x : { m: boolean; } - - // Should be able to detect a failure here - const x2 = { ->x2 : { m: true; s: string; } ->{ m: true, s: "false" } satisfies Facts : { m: true; s: string; } ->{ m: true, s: "false" } : { m: true; s: string; } - - m: true, ->m : true ->true : true - - s: "false" ->s : string ->"false" : "false" - - } satisfies Facts; -} - -namespace PropertyValueConformance2 { ->PropertyValueConformance2 : typeof PropertyValueConformance2 - - export type Color = { r: number, g: number, b: number }; ->Color : Color ->r : number ->g : number ->b : number - - // All of these should be Colors, but I only use some of them here. - export const Palette = { ->Palette : { white: { r: number; g: number; b: number; }; black: { r: number; g: number; d: number; }; blue: { r: number; g: number; b: number; }; } ->{ white: { r: 255, g: 255, b: 255 }, black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' blue: { r: 0, g: 0, b: 255 }, } satisfies Record : { white: { r: number; g: number; b: number; }; black: { r: number; g: number; d: number; }; blue: { r: number; g: number; b: number; }; } ->{ white: { r: 255, g: 255, b: 255 }, black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' blue: { r: 0, g: 0, b: 255 }, } : { white: { r: number; g: number; b: number; }; black: { r: number; g: number; d: number; }; blue: { r: number; g: number; b: number; }; } - - white: { r: 255, g: 255, b: 255 }, ->white : { r: number; g: number; b: number; } ->{ r: 255, g: 255, b: 255 } : { r: number; g: number; b: number; } ->r : number ->255 : 255 ->g : number ->255 : 255 ->b : number ->255 : 255 - - black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' ->black : { r: number; g: number; d: number; } ->{ r: 0, g: 0, d: 0 } : { r: number; g: number; d: number; } ->r : number ->0 : 0 ->g : number ->0 : 0 ->d : number ->0 : 0 - - blue: { r: 0, g: 0, b: 255 }, ->blue : { r: number; g: number; b: number; } ->{ r: 0, g: 0, b: 255 } : { r: number; g: number; b: number; } ->r : number ->0 : 0 ->g : number ->0 : 0 ->b : number ->255 : 255 - - } satisfies Record; -} - -namespace EnsureInterfaceImpl { ->EnsureInterfaceImpl : typeof EnsureInterfaceImpl - - type Movable = { ->Movable : Movable - - move(distance: number): void; ->move : (distance: number) => void ->distance : number - - }; - - const car = { ->car : { start(): void; move(d: number): void; stop(): void; } ->{ start() { }, move(d) { // d should be number }, stop() { } } satisfies Movable & Record : { start(): void; move(d: number): void; stop(): void; } ->{ start() { }, move(d) { // d should be number }, stop() { } } : { start(): void; move(d: number): void; stop(): void; } - - start() { }, ->start : () => void - - move(d) { ->move : (d: number) => void ->d : number - - // d should be number - }, - stop() { } ->stop : () => void - - } satisfies Movable & Record; -} - -namespace OptionalMemberConformance { ->OptionalMemberConformance : typeof OptionalMemberConformance - - type Point2d = { x: number, y: number }; ->Point2d : Point2d ->x : number ->y : number - - // Undesirable behavior today with type annotation - const a = { x: 10 } satisfies Partial; ->a : { x: number; } ->{ x: 10 } satisfies Partial : { x: number; } ->{ x: 10 } : { x: number; } ->x : number ->10 : 10 - - // Should OK - console.log(a.x.toFixed()); ->console.log(a.x.toFixed()) : void ->console.log : (...data: any[]) => void ->console : Console ->log : (...data: any[]) => void ->a.x.toFixed() : string ->a.x.toFixed : (fractionDigits?: number) => string ->a.x : number ->a : { x: number; } ->x : number ->toFixed : (fractionDigits?: number) => string - - // Should error - let p = a.y; ->p : any ->a.y : any ->a : { x: number; } ->y : any -} - -namespace ContextualTyping { ->ContextualTyping : typeof ContextualTyping - - type Predicates = { [s: string]: (n: number) => boolean }; ->Predicates : Predicates ->s : string ->n : number - - const p: Predicates = { ->p : Predicates ->{ isEven: n => n % 2 === 0, isOdd: n => n % 2 === 1 } : { isEven: (n: number) => boolean; isOdd: (n: number) => boolean; } - - isEven: n => n % 2 === 0, ->isEven : (n: number) => boolean ->n => n % 2 === 0 : (n: number) => boolean ->n : number ->n % 2 === 0 : boolean ->n % 2 : number ->n : number ->2 : 2 ->0 : 0 - - isOdd: n => n % 2 === 1 ->isOdd : (n: number) => boolean ->n => n % 2 === 1 : (n: number) => boolean ->n : number ->n % 2 === 1 : boolean ->n % 2 : number ->n : number ->2 : 2 ->1 : 1 - - }; -} diff --git a/tests/baselines/reference/typeSatisfaction.errors.txt b/tests/baselines/reference/typeSatisfaction.errors.txt index 679d8574e8b8d..c4b51c47684ac 100644 --- a/tests/baselines/reference/typeSatisfaction.errors.txt +++ b/tests/baselines/reference/typeSatisfaction.errors.txt @@ -2,9 +2,11 @@ tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts(12,20): Object literal may only specify known properties, and 'b' does not exist in type 'I1'. tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts(13,26): error TS1360: Type '{}' does not satisfy the expected type 'I1'. Property 'a' is missing in type '{}' but required in type 'I1'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts(24,23): error TS1360: Type '{ a: string; b: string; }' does not satisfy the expected type 'A'. + Object literal may only specify known properties, and 'b' does not exist in type 'A'. -==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts (2 errors) ==== +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts (3 errors) ==== interface I1 { a: number; } @@ -15,17 +17,28 @@ tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts(13,26): type T2 = (x: string) => void; - const a1 = { a: 1 } satisfies I1; // Ok - const a2 = { a: 1, b: 1 } satisfies I1; // Error + const t1 = { a: 1 } satisfies I1; // Ok + const t2 = { a: 1, b: 1 } satisfies I1; // Error ~~~~ !!! error TS1360: Type '{ a: number; b: number; }' does not satisfy the expected type 'I1'. !!! error TS1360: Object literal may only specify known properties, and 'b' does not exist in type 'I1'. - const a3 = { } satisfies I1; // Error + const t3 = { } satisfies I1; // Error ~~ !!! error TS1360: Type '{}' does not satisfy the expected type 'I1'. !!! error TS1360: Property 'a' is missing in type '{}' but required in type 'I1'. !!! related TS2728 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts:2:5: 'a' is declared here. - const a4: T1 = { a: "a" } satisfies T1; // Ok - const a5 = (m => m.substring(0)) satisfies T2; // Ok + const t4: T1 = { a: "a" } satisfies T1; // Ok + const t5 = (m => m.substring(0)) satisfies T2; // Ok + + const t6 = [1, 2] satisfies [number, number]; + + interface A { + a: string + } + let t7 = { a: 'test' } satisfies A; + let t8 = { a: 'test', b: 'test' } satisfies A; + ~~~~~~~~~ +!!! error TS1360: Type '{ a: string; b: string; }' does not satisfy the expected type 'A'. +!!! error TS1360: Object literal may only specify known properties, and 'b' does not exist in type 'A'. \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction.js b/tests/baselines/reference/typeSatisfaction.js index 3b649039d98ea..646ac82d2b3c4 100644 --- a/tests/baselines/reference/typeSatisfaction.js +++ b/tests/baselines/reference/typeSatisfaction.js @@ -9,17 +9,28 @@ type T1 = { type T2 = (x: string) => void; -const a1 = { a: 1 } satisfies I1; // Ok -const a2 = { a: 1, b: 1 } satisfies I1; // Error -const a3 = { } satisfies I1; // Error +const t1 = { a: 1 } satisfies I1; // Ok +const t2 = { a: 1, b: 1 } satisfies I1; // Error +const t3 = { } satisfies I1; // Error -const a4: T1 = { a: "a" } satisfies T1; // Ok -const a5 = (m => m.substring(0)) satisfies T2; // Ok +const t4: T1 = { a: "a" } satisfies T1; // Ok +const t5 = (m => m.substring(0)) satisfies T2; // Ok + +const t6 = [1, 2] satisfies [number, number]; + +interface A { + a: string +} +let t7 = { a: 'test' } satisfies A; +let t8 = { a: 'test', b: 'test' } satisfies A; //// [typeSatisfaction.js] -var a1 = { a: 1 }; // Ok -var a2 = { a: 1, b: 1 }; // Error -var a3 = {}; // Error -var a4 = { a: "a" }; // Ok -var a5 = (function (m) { return m.substring(0); }); // Ok +var t1 = { a: 1 }; // Ok +var t2 = { a: 1, b: 1 }; // Error +var t3 = {}; // Error +var t4 = { a: "a" }; // Ok +var t5 = (function (m) { return m.substring(0); }); // Ok +var t6 = [1, 2]; +var t7 = { a: 'test' }; +var t8 = { a: 'test', b: 'test' }; diff --git a/tests/baselines/reference/typeSatisfaction.symbols b/tests/baselines/reference/typeSatisfaction.symbols index 2eae603562b0a..fb1f272825c7b 100644 --- a/tests/baselines/reference/typeSatisfaction.symbols +++ b/tests/baselines/reference/typeSatisfaction.symbols @@ -17,32 +17,52 @@ type T2 = (x: string) => void; >T2 : Symbol(T2, Decl(typeSatisfaction.ts, 6, 1)) >x : Symbol(x, Decl(typeSatisfaction.ts, 8, 11)) -const a1 = { a: 1 } satisfies I1; // Ok ->a1 : Symbol(a1, Decl(typeSatisfaction.ts, 10, 5)) +const t1 = { a: 1 } satisfies I1; // Ok +>t1 : Symbol(t1, Decl(typeSatisfaction.ts, 10, 5)) >a : Symbol(a, Decl(typeSatisfaction.ts, 10, 12)) >I1 : Symbol(I1, Decl(typeSatisfaction.ts, 0, 0)) -const a2 = { a: 1, b: 1 } satisfies I1; // Error ->a2 : Symbol(a2, Decl(typeSatisfaction.ts, 11, 5)) +const t2 = { a: 1, b: 1 } satisfies I1; // Error +>t2 : Symbol(t2, Decl(typeSatisfaction.ts, 11, 5)) >a : Symbol(a, Decl(typeSatisfaction.ts, 11, 12)) >b : Symbol(b, Decl(typeSatisfaction.ts, 11, 18)) >I1 : Symbol(I1, Decl(typeSatisfaction.ts, 0, 0)) -const a3 = { } satisfies I1; // Error ->a3 : Symbol(a3, Decl(typeSatisfaction.ts, 12, 5)) +const t3 = { } satisfies I1; // Error +>t3 : Symbol(t3, Decl(typeSatisfaction.ts, 12, 5)) >I1 : Symbol(I1, Decl(typeSatisfaction.ts, 0, 0)) -const a4: T1 = { a: "a" } satisfies T1; // Ok ->a4 : Symbol(a4, Decl(typeSatisfaction.ts, 14, 5)) +const t4: T1 = { a: "a" } satisfies T1; // Ok +>t4 : Symbol(t4, Decl(typeSatisfaction.ts, 14, 5)) >T1 : Symbol(T1, Decl(typeSatisfaction.ts, 2, 1)) >a : Symbol(a, Decl(typeSatisfaction.ts, 14, 16)) >T1 : Symbol(T1, Decl(typeSatisfaction.ts, 2, 1)) -const a5 = (m => m.substring(0)) satisfies T2; // Ok ->a5 : Symbol(a5, Decl(typeSatisfaction.ts, 15, 5)) +const t5 = (m => m.substring(0)) satisfies T2; // Ok +>t5 : Symbol(t5, Decl(typeSatisfaction.ts, 15, 5)) >m : Symbol(m, Decl(typeSatisfaction.ts, 15, 12)) >m.substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) >m : Symbol(m, Decl(typeSatisfaction.ts, 15, 12)) >substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) >T2 : Symbol(T2, Decl(typeSatisfaction.ts, 6, 1)) +const t6 = [1, 2] satisfies [number, number]; +>t6 : Symbol(t6, Decl(typeSatisfaction.ts, 17, 5)) + +interface A { +>A : Symbol(A, Decl(typeSatisfaction.ts, 17, 45)) + + a: string +>a : Symbol(A.a, Decl(typeSatisfaction.ts, 19, 13)) +} +let t7 = { a: 'test' } satisfies A; +>t7 : Symbol(t7, Decl(typeSatisfaction.ts, 22, 3)) +>a : Symbol(a, Decl(typeSatisfaction.ts, 22, 10)) +>A : Symbol(A, Decl(typeSatisfaction.ts, 17, 45)) + +let t8 = { a: 'test', b: 'test' } satisfies A; +>t8 : Symbol(t8, Decl(typeSatisfaction.ts, 23, 3)) +>a : Symbol(a, Decl(typeSatisfaction.ts, 23, 10)) +>b : Symbol(b, Decl(typeSatisfaction.ts, 23, 21)) +>A : Symbol(A, Decl(typeSatisfaction.ts, 17, 45)) + diff --git a/tests/baselines/reference/typeSatisfaction.types b/tests/baselines/reference/typeSatisfaction.types index fff207ffa0534..ec86d62a592c2 100644 --- a/tests/baselines/reference/typeSatisfaction.types +++ b/tests/baselines/reference/typeSatisfaction.types @@ -15,15 +15,15 @@ type T2 = (x: string) => void; >T2 : T2 >x : string -const a1 = { a: 1 } satisfies I1; // Ok ->a1 : { a: number; } +const t1 = { a: 1 } satisfies I1; // Ok +>t1 : { a: number; } >{ a: 1 } satisfies I1 : { a: number; } >{ a: 1 } : { a: number; } >a : number >1 : 1 -const a2 = { a: 1, b: 1 } satisfies I1; // Error ->a2 : { a: number; b: number; } +const t2 = { a: 1, b: 1 } satisfies I1; // Error +>t2 : { a: number; b: number; } >{ a: 1, b: 1 } satisfies I1 : { a: number; b: number; } >{ a: 1, b: 1 } : { a: number; b: number; } >a : number @@ -31,20 +31,20 @@ const a2 = { a: 1, b: 1 } satisfies I1; // Error >b : number >1 : 1 -const a3 = { } satisfies I1; // Error ->a3 : {} +const t3 = { } satisfies I1; // Error +>t3 : {} >{ } satisfies I1 : {} >{ } : {} -const a4: T1 = { a: "a" } satisfies T1; // Ok ->a4 : T1 +const t4: T1 = { a: "a" } satisfies T1; // Ok +>t4 : T1 >{ a: "a" } satisfies T1 : { a: "a"; } >{ a: "a" } : { a: "a"; } >a : "a" >"a" : "a" -const a5 = (m => m.substring(0)) satisfies T2; // Ok ->a5 : (m: string) => string +const t5 = (m => m.substring(0)) satisfies T2; // Ok +>t5 : (m: string) => string >(m => m.substring(0)) satisfies T2 : (m: string) => string >(m => m.substring(0)) : (m: string) => string >m => m.substring(0) : (m: string) => string @@ -55,3 +55,30 @@ const a5 = (m => m.substring(0)) satisfies T2; // Ok >substring : (start: number, end?: number) => string >0 : 0 +const t6 = [1, 2] satisfies [number, number]; +>t6 : [number, number] +>[1, 2] satisfies [number, number] : [number, number] +>[1, 2] : [number, number] +>1 : 1 +>2 : 2 + +interface A { + a: string +>a : string +} +let t7 = { a: 'test' } satisfies A; +>t7 : { a: string; } +>{ a: 'test' } satisfies A : { a: string; } +>{ a: 'test' } : { a: string; } +>a : string +>'test' : "test" + +let t8 = { a: 'test', b: 'test' } satisfies A; +>t8 : { a: string; b: string; } +>{ a: 'test', b: 'test' } satisfies A : { a: string; b: string; } +>{ a: 'test', b: 'test' } : { a: string; b: string; } +>a : string +>'test' : "test" +>b : string +>'test' : "test" + diff --git a/tests/baselines/reference/typeSatisfaction_contextualTyping1.js b/tests/baselines/reference/typeSatisfaction_contextualTyping1.js new file mode 100644 index 0000000000000..e8b5cd7246e0d --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_contextualTyping1.js @@ -0,0 +1,14 @@ +//// [typeSatisfaction_contextualTyping1.ts] +type Predicates = { [s: string]: (n: number) => boolean }; + +const p = { + isEven: n => n % 2 === 0, + isOdd: n => n % 2 === 1 +} satisfies Predicates; + + +//// [typeSatisfaction_contextualTyping1.js] +var p = { + isEven: function (n) { return n % 2 === 0; }, + isOdd: function (n) { return n % 2 === 1; } +}; diff --git a/tests/baselines/reference/typeSatisfaction_contextualTyping1.symbols b/tests/baselines/reference/typeSatisfaction_contextualTyping1.symbols new file mode 100644 index 0000000000000..0b44d64dd6ea4 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_contextualTyping1.symbols @@ -0,0 +1,22 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping1.ts === +type Predicates = { [s: string]: (n: number) => boolean }; +>Predicates : Symbol(Predicates, Decl(typeSatisfaction_contextualTyping1.ts, 0, 0)) +>s : Symbol(s, Decl(typeSatisfaction_contextualTyping1.ts, 0, 21)) +>n : Symbol(n, Decl(typeSatisfaction_contextualTyping1.ts, 0, 34)) + +const p = { +>p : Symbol(p, Decl(typeSatisfaction_contextualTyping1.ts, 2, 5)) + + isEven: n => n % 2 === 0, +>isEven : Symbol(isEven, Decl(typeSatisfaction_contextualTyping1.ts, 2, 11)) +>n : Symbol(n, Decl(typeSatisfaction_contextualTyping1.ts, 3, 11)) +>n : Symbol(n, Decl(typeSatisfaction_contextualTyping1.ts, 3, 11)) + + isOdd: n => n % 2 === 1 +>isOdd : Symbol(isOdd, Decl(typeSatisfaction_contextualTyping1.ts, 3, 29)) +>n : Symbol(n, Decl(typeSatisfaction_contextualTyping1.ts, 4, 10)) +>n : Symbol(n, Decl(typeSatisfaction_contextualTyping1.ts, 4, 10)) + +} satisfies Predicates; +>Predicates : Symbol(Predicates, Decl(typeSatisfaction_contextualTyping1.ts, 0, 0)) + diff --git a/tests/baselines/reference/typeSatisfaction_contextualTyping1.types b/tests/baselines/reference/typeSatisfaction_contextualTyping1.types new file mode 100644 index 0000000000000..59a368a89684c --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_contextualTyping1.types @@ -0,0 +1,33 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping1.ts === +type Predicates = { [s: string]: (n: number) => boolean }; +>Predicates : Predicates +>s : string +>n : number + +const p = { +>p : { isEven: (n: number) => boolean; isOdd: (n: number) => boolean; } +>{ isEven: n => n % 2 === 0, isOdd: n => n % 2 === 1} satisfies Predicates : { isEven: (n: number) => boolean; isOdd: (n: number) => boolean; } +>{ isEven: n => n % 2 === 0, isOdd: n => n % 2 === 1} : { isEven: (n: number) => boolean; isOdd: (n: number) => boolean; } + + isEven: n => n % 2 === 0, +>isEven : (n: number) => boolean +>n => n % 2 === 0 : (n: number) => boolean +>n : number +>n % 2 === 0 : boolean +>n % 2 : number +>n : number +>2 : 2 +>0 : 0 + + isOdd: n => n % 2 === 1 +>isOdd : (n: number) => boolean +>n => n % 2 === 1 : (n: number) => boolean +>n : number +>n % 2 === 1 : boolean +>n % 2 : number +>n : number +>2 : 2 +>1 : 1 + +} satisfies Predicates; + diff --git a/tests/baselines/reference/satisfiesContextualType.js b/tests/baselines/reference/typeSatisfaction_contextualTyping2.js similarity index 81% rename from tests/baselines/reference/satisfiesContextualType.js rename to tests/baselines/reference/typeSatisfaction_contextualTyping2.js index 656885d6409a4..a8c0bb41ece47 100644 --- a/tests/baselines/reference/satisfiesContextualType.js +++ b/tests/baselines/reference/typeSatisfaction_contextualTyping2.js @@ -1,4 +1,4 @@ -//// [satisfiesContextualType.ts] +//// [typeSatisfaction_contextualTyping2.ts] let obj: { f(s: string): void } & Record = { f(s) { }, // "incorrect" implicit any on 's' g(s) { } @@ -8,7 +8,7 @@ let obj: { f(s: string): void } & Record = { ({ f(x) { } }) satisfies { f(s: string): void }; -//// [satisfiesContextualType.js] +//// [typeSatisfaction_contextualTyping2.js] "use strict"; var obj = { f: function (s) { }, diff --git a/tests/baselines/reference/typeSatisfaction_contextualTyping2.symbols b/tests/baselines/reference/typeSatisfaction_contextualTyping2.symbols new file mode 100644 index 0000000000000..d7bda841fb6d7 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_contextualTyping2.symbols @@ -0,0 +1,27 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping2.ts === +let obj: { f(s: string): void } & Record = { +>obj : Symbol(obj, Decl(typeSatisfaction_contextualTyping2.ts, 0, 3)) +>f : Symbol(f, Decl(typeSatisfaction_contextualTyping2.ts, 0, 10)) +>s : Symbol(s, Decl(typeSatisfaction_contextualTyping2.ts, 0, 13)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + + f(s) { }, // "incorrect" implicit any on 's' +>f : Symbol(f, Decl(typeSatisfaction_contextualTyping2.ts, 0, 61)) +>s : Symbol(s, Decl(typeSatisfaction_contextualTyping2.ts, 1, 6)) + + g(s) { } +>g : Symbol(g, Decl(typeSatisfaction_contextualTyping2.ts, 1, 13)) +>s : Symbol(s, Decl(typeSatisfaction_contextualTyping2.ts, 2, 6)) + +} satisfies { g(s: string): void } & Record; +>g : Symbol(g, Decl(typeSatisfaction_contextualTyping2.ts, 3, 13)) +>s : Symbol(s, Decl(typeSatisfaction_contextualTyping2.ts, 3, 16)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +// This needs to not crash (outer node is not expression) +({ f(x) { } }) satisfies { f(s: string): void }; +>f : Symbol(f, Decl(typeSatisfaction_contextualTyping2.ts, 6, 2)) +>x : Symbol(x, Decl(typeSatisfaction_contextualTyping2.ts, 6, 5)) +>f : Symbol(f, Decl(typeSatisfaction_contextualTyping2.ts, 6, 26)) +>s : Symbol(s, Decl(typeSatisfaction_contextualTyping2.ts, 6, 29)) + diff --git a/tests/baselines/reference/satisfiesContextualType.types b/tests/baselines/reference/typeSatisfaction_contextualTyping2.types similarity index 88% rename from tests/baselines/reference/satisfiesContextualType.types rename to tests/baselines/reference/typeSatisfaction_contextualTyping2.types index a1d995063054e..9d9e83d09c5ed 100644 --- a/tests/baselines/reference/satisfiesContextualType.types +++ b/tests/baselines/reference/typeSatisfaction_contextualTyping2.types @@ -1,4 +1,4 @@ -=== tests/cases/compiler/satisfiesContextualType.ts === +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping2.ts === let obj: { f(s: string): void } & Record = { >obj : { f(s: string): void; } & Record >f : (s: string) => void diff --git a/tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.js b/tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.js new file mode 100644 index 0000000000000..e33ac953b454a --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.js @@ -0,0 +1,22 @@ +//// [typeSatisfaction_ensureInterfaceImpl.ts] +type Movable = { + move(distance: number): void; +}; + +const car = { + start() { }, + move(d) { + // d should be number + }, + stop() { } +} satisfies Movable & Record; + + +//// [typeSatisfaction_ensureInterfaceImpl.js] +var car = { + start: function () { }, + move: function (d) { + // d should be number + }, + stop: function () { } +}; diff --git a/tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.symbols b/tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.symbols new file mode 100644 index 0000000000000..afcab39149964 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_ensureInterfaceImpl.ts === +type Movable = { +>Movable : Symbol(Movable, Decl(typeSatisfaction_ensureInterfaceImpl.ts, 0, 0)) + + move(distance: number): void; +>move : Symbol(move, Decl(typeSatisfaction_ensureInterfaceImpl.ts, 0, 16)) +>distance : Symbol(distance, Decl(typeSatisfaction_ensureInterfaceImpl.ts, 1, 9)) + +}; + +const car = { +>car : Symbol(car, Decl(typeSatisfaction_ensureInterfaceImpl.ts, 4, 5)) + + start() { }, +>start : Symbol(start, Decl(typeSatisfaction_ensureInterfaceImpl.ts, 4, 13)) + + move(d) { +>move : Symbol(move, Decl(typeSatisfaction_ensureInterfaceImpl.ts, 5, 16)) +>d : Symbol(d, Decl(typeSatisfaction_ensureInterfaceImpl.ts, 6, 9)) + + // d should be number + }, + stop() { } +>stop : Symbol(stop, Decl(typeSatisfaction_ensureInterfaceImpl.ts, 8, 6)) + +} satisfies Movable & Record; +>Movable : Symbol(Movable, Decl(typeSatisfaction_ensureInterfaceImpl.ts, 0, 0)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + diff --git a/tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.types b/tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.types new file mode 100644 index 0000000000000..392b6b896cfa2 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_ensureInterfaceImpl.types @@ -0,0 +1,29 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_ensureInterfaceImpl.ts === +type Movable = { +>Movable : Movable + + move(distance: number): void; +>move : (distance: number) => void +>distance : number + +}; + +const car = { +>car : { start(): void; move(d: number): void; stop(): void; } +>{ start() { }, move(d) { // d should be number }, stop() { }} satisfies Movable & Record : { start(): void; move(d: number): void; stop(): void; } +>{ start() { }, move(d) { // d should be number }, stop() { }} : { start(): void; move(d: number): void; stop(): void; } + + start() { }, +>start : () => void + + move(d) { +>move : (d: number) => void +>d : number + + // d should be number + }, + stop() { } +>stop : () => void + +} satisfies Movable & Record; + diff --git a/tests/baselines/reference/jsFileCompilationTypeSatisfaction.errors.txt b/tests/baselines/reference/typeSatisfaction_js.errors.txt similarity index 100% rename from tests/baselines/reference/jsFileCompilationTypeSatisfaction.errors.txt rename to tests/baselines/reference/typeSatisfaction_js.errors.txt diff --git a/tests/baselines/reference/jsFileCompilationTypeSatisfaction.js b/tests/baselines/reference/typeSatisfaction_js.js similarity index 100% rename from tests/baselines/reference/jsFileCompilationTypeSatisfaction.js rename to tests/baselines/reference/typeSatisfaction_js.js diff --git a/tests/baselines/reference/jsFileCompilationTypeSatisfaction.symbols b/tests/baselines/reference/typeSatisfaction_js.symbols similarity index 100% rename from tests/baselines/reference/jsFileCompilationTypeSatisfaction.symbols rename to tests/baselines/reference/typeSatisfaction_js.symbols diff --git a/tests/baselines/reference/jsFileCompilationTypeSatisfaction.types b/tests/baselines/reference/typeSatisfaction_js.types similarity index 100% rename from tests/baselines/reference/jsFileCompilationTypeSatisfaction.types rename to tests/baselines/reference/typeSatisfaction_js.types diff --git a/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.errors.txt b/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.errors.txt new file mode 100644 index 0000000000000..c45de3250dcd0 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_optionalMemberConformance.ts(7,11): error TS2339: Property 'y' does not exist on type '{ x: number; }'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_optionalMemberConformance.ts (1 errors) ==== + type Point2d = { x: number, y: number }; + // Undesirable behavior today with type annotation + const a = { x: 10 } satisfies Partial; + // Should OK + console.log(a.x.toFixed()); + // Should error + let p = a.y; + ~ +!!! error TS2339: Property 'y' does not exist on type '{ x: number; }'. + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.js b/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.js new file mode 100644 index 0000000000000..d21648cfb19f9 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.js @@ -0,0 +1,17 @@ +//// [typeSatisfaction_optionalMemberConformance.ts] +type Point2d = { x: number, y: number }; +// Undesirable behavior today with type annotation +const a = { x: 10 } satisfies Partial; +// Should OK +console.log(a.x.toFixed()); +// Should error +let p = a.y; + + +//// [typeSatisfaction_optionalMemberConformance.js] +// Undesirable behavior today with type annotation +var a = { x: 10 }; +// Should OK +console.log(a.x.toFixed()); +// Should error +var p = a.y; diff --git a/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.symbols b/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.symbols new file mode 100644 index 0000000000000..d1f6bbc0470d2 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_optionalMemberConformance.ts === +type Point2d = { x: number, y: number }; +>Point2d : Symbol(Point2d, Decl(typeSatisfaction_optionalMemberConformance.ts, 0, 0)) +>x : Symbol(x, Decl(typeSatisfaction_optionalMemberConformance.ts, 0, 16)) +>y : Symbol(y, Decl(typeSatisfaction_optionalMemberConformance.ts, 0, 27)) + +// Undesirable behavior today with type annotation +const a = { x: 10 } satisfies Partial; +>a : Symbol(a, Decl(typeSatisfaction_optionalMemberConformance.ts, 2, 5)) +>x : Symbol(x, Decl(typeSatisfaction_optionalMemberConformance.ts, 2, 11)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>Point2d : Symbol(Point2d, Decl(typeSatisfaction_optionalMemberConformance.ts, 0, 0)) + +// Should OK +console.log(a.x.toFixed()); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>a.x.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>a.x : Symbol(x, Decl(typeSatisfaction_optionalMemberConformance.ts, 2, 11)) +>a : Symbol(a, Decl(typeSatisfaction_optionalMemberConformance.ts, 2, 5)) +>x : Symbol(x, Decl(typeSatisfaction_optionalMemberConformance.ts, 2, 11)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + +// Should error +let p = a.y; +>p : Symbol(p, Decl(typeSatisfaction_optionalMemberConformance.ts, 6, 3)) +>a : Symbol(a, Decl(typeSatisfaction_optionalMemberConformance.ts, 2, 5)) + diff --git a/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.types b/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.types new file mode 100644 index 0000000000000..bf0e02babfba2 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_optionalMemberConformance.types @@ -0,0 +1,34 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_optionalMemberConformance.ts === +type Point2d = { x: number, y: number }; +>Point2d : Point2d +>x : number +>y : number + +// Undesirable behavior today with type annotation +const a = { x: 10 } satisfies Partial; +>a : { x: number; } +>{ x: 10 } satisfies Partial : { x: number; } +>{ x: 10 } : { x: number; } +>x : number +>10 : 10 + +// Should OK +console.log(a.x.toFixed()); +>console.log(a.x.toFixed()) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>a.x.toFixed() : string +>a.x.toFixed : (fractionDigits?: number) => string +>a.x : number +>a : { x: number; } +>x : number +>toFixed : (fractionDigits?: number) => string + +// Should error +let p = a.y; +>p : any +>a.y : any +>a : { x: number; } +>y : any + diff --git a/tests/baselines/reference/typeSatisfaction_propNameConstraining.errors.txt b/tests/baselines/reference/typeSatisfaction_propNameConstraining.errors.txt new file mode 100644 index 0000000000000..a0162567a7f91 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propNameConstraining.errors.txt @@ -0,0 +1,25 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propNameConstraining.ts(6,5): error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Partial>'. + Object literal may only specify known properties, and 'x' does not exist in type 'Partial>'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propNameConstraining.ts(13,11): error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propNameConstraining.ts (2 errors) ==== + type Keys = 'a' | 'b' | 'c' | 'd'; + + const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' + ~~~~ +!!! error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Partial>'. +!!! error TS1360: Object literal may only specify known properties, and 'x' does not exist in type 'Partial>'. + } satisfies Partial>; + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); + let b = p.b.substring(1); + // Should error even though 'd' is in 'Keys' + let d = p.d; + ~ +!!! error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_propNameConstraining.js b/tests/baselines/reference/typeSatisfaction_propNameConstraining.js new file mode 100644 index 0000000000000..64490c480a682 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propNameConstraining.js @@ -0,0 +1,27 @@ +//// [typeSatisfaction_propNameConstraining.ts] +type Keys = 'a' | 'b' | 'c' | 'd'; + +const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' +} satisfies Partial>; + +// Should be OK -- retain info that a is number and b is string +let a = p.a.toFixed(); +let b = p.b.substring(1); +// Should error even though 'd' is in 'Keys' +let d = p.d; + + +//// [typeSatisfaction_propNameConstraining.js] +var p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' +}; +// Should be OK -- retain info that a is number and b is string +var a = p.a.toFixed(); +var b = p.b.substring(1); +// Should error even though 'd' is in 'Keys' +var d = p.d; diff --git a/tests/baselines/reference/typeSatisfaction_propNameConstraining.symbols b/tests/baselines/reference/typeSatisfaction_propNameConstraining.symbols new file mode 100644 index 0000000000000..d846ceda53396 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propNameConstraining.symbols @@ -0,0 +1,43 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propNameConstraining.ts === +type Keys = 'a' | 'b' | 'c' | 'd'; +>Keys : Symbol(Keys, Decl(typeSatisfaction_propNameConstraining.ts, 0, 0)) + +const p = { +>p : Symbol(p, Decl(typeSatisfaction_propNameConstraining.ts, 2, 5)) + + a: 0, +>a : Symbol(a, Decl(typeSatisfaction_propNameConstraining.ts, 2, 11)) + + b: "hello", +>b : Symbol(b, Decl(typeSatisfaction_propNameConstraining.ts, 3, 9)) + + x: 8 // Should error, 'x' isn't in 'Keys' +>x : Symbol(x, Decl(typeSatisfaction_propNameConstraining.ts, 4, 15)) + +} satisfies Partial>; +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>Keys : Symbol(Keys, Decl(typeSatisfaction_propNameConstraining.ts, 0, 0)) + +// Should be OK -- retain info that a is number and b is string +let a = p.a.toFixed(); +>a : Symbol(a, Decl(typeSatisfaction_propNameConstraining.ts, 9, 3)) +>p.a.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>p.a : Symbol(a, Decl(typeSatisfaction_propNameConstraining.ts, 2, 11)) +>p : Symbol(p, Decl(typeSatisfaction_propNameConstraining.ts, 2, 5)) +>a : Symbol(a, Decl(typeSatisfaction_propNameConstraining.ts, 2, 11)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + +let b = p.b.substring(1); +>b : Symbol(b, Decl(typeSatisfaction_propNameConstraining.ts, 10, 3)) +>p.b.substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) +>p.b : Symbol(b, Decl(typeSatisfaction_propNameConstraining.ts, 3, 9)) +>p : Symbol(p, Decl(typeSatisfaction_propNameConstraining.ts, 2, 5)) +>b : Symbol(b, Decl(typeSatisfaction_propNameConstraining.ts, 3, 9)) +>substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) + +// Should error even though 'd' is in 'Keys' +let d = p.d; +>d : Symbol(d, Decl(typeSatisfaction_propNameConstraining.ts, 12, 3)) +>p : Symbol(p, Decl(typeSatisfaction_propNameConstraining.ts, 2, 5)) + diff --git a/tests/baselines/reference/typeSatisfaction_propNameConstraining.types b/tests/baselines/reference/typeSatisfaction_propNameConstraining.types new file mode 100644 index 0000000000000..4a9bc9a56ff1c --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propNameConstraining.types @@ -0,0 +1,50 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propNameConstraining.ts === +type Keys = 'a' | 'b' | 'c' | 'd'; +>Keys : Keys + +const p = { +>p : { a: number; b: string; x: number; } +>{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys'} satisfies Partial> : { a: number; b: string; x: number; } +>{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys'} : { a: number; b: string; x: number; } + + a: 0, +>a : number +>0 : 0 + + b: "hello", +>b : string +>"hello" : "hello" + + x: 8 // Should error, 'x' isn't in 'Keys' +>x : number +>8 : 8 + +} satisfies Partial>; + +// Should be OK -- retain info that a is number and b is string +let a = p.a.toFixed(); +>a : string +>p.a.toFixed() : string +>p.a.toFixed : (fractionDigits?: number) => string +>p.a : number +>p : { a: number; b: string; x: number; } +>a : number +>toFixed : (fractionDigits?: number) => string + +let b = p.b.substring(1); +>b : string +>p.b.substring(1) : string +>p.b.substring : (start: number, end?: number) => string +>p.b : string +>p : { a: number; b: string; x: number; } +>b : string +>substring : (start: number, end?: number) => string +>1 : 1 + +// Should error even though 'd' is in 'Keys' +let d = p.d; +>d : any +>p.d : any +>p : { a: number; b: string; x: number; } +>d : any + diff --git a/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.errors.txt b/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.errors.txt new file mode 100644 index 0000000000000..dbcb6fd41950c --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.errors.txt @@ -0,0 +1,25 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyNameFulfillment.ts(6,5): error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Record'. + Object literal may only specify known properties, and 'x' does not exist in type 'Record'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyNameFulfillment.ts(13,11): error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyNameFulfillment.ts (2 errors) ==== + type Keys = 'a' | 'b' | 'c' | 'd'; + + const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' + ~~~~ +!!! error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Record'. +!!! error TS1360: Object literal may only specify known properties, and 'x' does not exist in type 'Record'. + } satisfies Record; + + // Should be OK -- retain info that a is number and b is string + let a = p.a.toFixed(); + let b = p.b.substring(1); + // Should error even though 'd' is in 'Keys' + let d = p.d; + ~ +!!! error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'. + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.js b/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.js new file mode 100644 index 0000000000000..1bea49e03def3 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.js @@ -0,0 +1,27 @@ +//// [typeSatisfaction_propertyNameFulfillment.ts] +type Keys = 'a' | 'b' | 'c' | 'd'; + +const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' +} satisfies Record; + +// Should be OK -- retain info that a is number and b is string +let a = p.a.toFixed(); +let b = p.b.substring(1); +// Should error even though 'd' is in 'Keys' +let d = p.d; + + +//// [typeSatisfaction_propertyNameFulfillment.js] +var p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' +}; +// Should be OK -- retain info that a is number and b is string +var a = p.a.toFixed(); +var b = p.b.substring(1); +// Should error even though 'd' is in 'Keys' +var d = p.d; diff --git a/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.symbols b/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.symbols new file mode 100644 index 0000000000000..824fa99634540 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.symbols @@ -0,0 +1,42 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyNameFulfillment.ts === +type Keys = 'a' | 'b' | 'c' | 'd'; +>Keys : Symbol(Keys, Decl(typeSatisfaction_propertyNameFulfillment.ts, 0, 0)) + +const p = { +>p : Symbol(p, Decl(typeSatisfaction_propertyNameFulfillment.ts, 2, 5)) + + a: 0, +>a : Symbol(a, Decl(typeSatisfaction_propertyNameFulfillment.ts, 2, 11)) + + b: "hello", +>b : Symbol(b, Decl(typeSatisfaction_propertyNameFulfillment.ts, 3, 9)) + + x: 8 // Should error, 'x' isn't in 'Keys' +>x : Symbol(x, Decl(typeSatisfaction_propertyNameFulfillment.ts, 4, 15)) + +} satisfies Record; +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>Keys : Symbol(Keys, Decl(typeSatisfaction_propertyNameFulfillment.ts, 0, 0)) + +// Should be OK -- retain info that a is number and b is string +let a = p.a.toFixed(); +>a : Symbol(a, Decl(typeSatisfaction_propertyNameFulfillment.ts, 9, 3)) +>p.a.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>p.a : Symbol(a, Decl(typeSatisfaction_propertyNameFulfillment.ts, 2, 11)) +>p : Symbol(p, Decl(typeSatisfaction_propertyNameFulfillment.ts, 2, 5)) +>a : Symbol(a, Decl(typeSatisfaction_propertyNameFulfillment.ts, 2, 11)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + +let b = p.b.substring(1); +>b : Symbol(b, Decl(typeSatisfaction_propertyNameFulfillment.ts, 10, 3)) +>p.b.substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) +>p.b : Symbol(b, Decl(typeSatisfaction_propertyNameFulfillment.ts, 3, 9)) +>p : Symbol(p, Decl(typeSatisfaction_propertyNameFulfillment.ts, 2, 5)) +>b : Symbol(b, Decl(typeSatisfaction_propertyNameFulfillment.ts, 3, 9)) +>substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) + +// Should error even though 'd' is in 'Keys' +let d = p.d; +>d : Symbol(d, Decl(typeSatisfaction_propertyNameFulfillment.ts, 12, 3)) +>p : Symbol(p, Decl(typeSatisfaction_propertyNameFulfillment.ts, 2, 5)) + diff --git a/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.types b/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.types new file mode 100644 index 0000000000000..55d07be121f38 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyNameFulfillment.types @@ -0,0 +1,50 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyNameFulfillment.ts === +type Keys = 'a' | 'b' | 'c' | 'd'; +>Keys : Keys + +const p = { +>p : { a: number; b: string; x: number; } +>{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys'} satisfies Record : { a: number; b: string; x: number; } +>{ a: 0, b: "hello", x: 8 // Should error, 'x' isn't in 'Keys'} : { a: number; b: string; x: number; } + + a: 0, +>a : number +>0 : 0 + + b: "hello", +>b : string +>"hello" : "hello" + + x: 8 // Should error, 'x' isn't in 'Keys' +>x : number +>8 : 8 + +} satisfies Record; + +// Should be OK -- retain info that a is number and b is string +let a = p.a.toFixed(); +>a : string +>p.a.toFixed() : string +>p.a.toFixed : (fractionDigits?: number) => string +>p.a : number +>p : { a: number; b: string; x: number; } +>a : number +>toFixed : (fractionDigits?: number) => string + +let b = p.b.substring(1); +>b : string +>p.b.substring(1) : string +>p.b.substring : (start: number, end?: number) => string +>p.b : string +>p : { a: number; b: string; x: number; } +>b : string +>substring : (start: number, end?: number) => string +>1 : 1 + +// Should error even though 'd' is in 'Keys' +let d = p.d; +>d : any +>p.d : any +>p : { a: number; b: string; x: number; } +>d : any + diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).errors.txt b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).errors.txt new file mode 100644 index 0000000000000..fd603a7727578 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).errors.txt @@ -0,0 +1,34 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts(13,15): error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts(22,5): error TS2322: Type 'string' is not assignable to type 'boolean'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts (2 errors) ==== + type Facts = { [key: string]: boolean }; + declare function checkTruths(x: Facts): void; + declare function checkM(x: { m: boolean }): void; + const x = { + m: true + }; + + // Should be OK + checkTruths(x); + // Should be OK + checkM(x); + // Should fail under --noPropertyAccessFromIndexSignature + console.log(x.z); + ~ +!!! error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. + const m: boolean = x.m; + + // Should be 'm' + type M = keyof typeof x; + + // Should be able to detect a failure here + const x2 = { + m: true, + s: "false" + ~ +!!! error TS2322: Type 'string' is not assignable to type 'boolean'. +!!! related TS6501 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts:1:16: The expected type comes from this index signature. + } satisfies Facts; + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).js b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).js new file mode 100644 index 0000000000000..f0afe57b996ee --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).js @@ -0,0 +1,42 @@ +//// [typeSatisfaction_propertyValueConformance1.ts] +type Facts = { [key: string]: boolean }; +declare function checkTruths(x: Facts): void; +declare function checkM(x: { m: boolean }): void; +const x = { + m: true +}; + +// Should be OK +checkTruths(x); +// Should be OK +checkM(x); +// Should fail under --noPropertyAccessFromIndexSignature +console.log(x.z); +const m: boolean = x.m; + +// Should be 'm' +type M = keyof typeof x; + +// Should be able to detect a failure here +const x2 = { + m: true, + s: "false" +} satisfies Facts; + + +//// [typeSatisfaction_propertyValueConformance1.js] +var x = { + m: true +}; +// Should be OK +checkTruths(x); +// Should be OK +checkM(x); +// Should fail under --noPropertyAccessFromIndexSignature +console.log(x.z); +var m = x.m; +// Should be able to detect a failure here +var x2 = { + m: true, + s: "false" +}; diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).symbols b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).symbols new file mode 100644 index 0000000000000..640357f878186 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).symbols @@ -0,0 +1,64 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts === +type Facts = { [key: string]: boolean }; +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 0)) +>key : Symbol(key, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 16)) + +declare function checkTruths(x: Facts): void; +>checkTruths : Symbol(checkTruths, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 40)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 1, 29)) +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 0)) + +declare function checkM(x: { m: boolean }): void; +>checkM : Symbol(checkM, Decl(typeSatisfaction_propertyValueConformance1.ts, 1, 45)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 2, 24)) +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 2, 28)) + +const x = { +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) + + m: true +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 11)) + +}; + +// Should be OK +checkTruths(x); +>checkTruths : Symbol(checkTruths, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 40)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) + +// Should be OK +checkM(x); +>checkM : Symbol(checkM, Decl(typeSatisfaction_propertyValueConformance1.ts, 1, 45)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) + +// Should fail under --noPropertyAccessFromIndexSignature +console.log(x.z); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) + +const m: boolean = x.m; +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 13, 5)) +>x.m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 11)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 11)) + +// Should be 'm' +type M = keyof typeof x; +>M : Symbol(M, Decl(typeSatisfaction_propertyValueConformance1.ts, 13, 23)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) + +// Should be able to detect a failure here +const x2 = { +>x2 : Symbol(x2, Decl(typeSatisfaction_propertyValueConformance1.ts, 19, 5)) + + m: true, +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 19, 12)) + + s: "false" +>s : Symbol(s, Decl(typeSatisfaction_propertyValueConformance1.ts, 20, 12)) + +} satisfies Facts; +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 0)) + diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).types b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).types new file mode 100644 index 0000000000000..718224c6f5d1d --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=false).types @@ -0,0 +1,73 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts === +type Facts = { [key: string]: boolean }; +>Facts : Facts +>key : string + +declare function checkTruths(x: Facts): void; +>checkTruths : (x: Facts) => void +>x : Facts + +declare function checkM(x: { m: boolean }): void; +>checkM : (x: { m: boolean;}) => void +>x : { m: boolean; } +>m : boolean + +const x = { +>x : { m: boolean; } +>{ m: true} : { m: boolean; } + + m: true +>m : boolean +>true : true + +}; + +// Should be OK +checkTruths(x); +>checkTruths(x) : void +>checkTruths : (x: Facts) => void +>x : { m: boolean; } + +// Should be OK +checkM(x); +>checkM(x) : void +>checkM : (x: { m: boolean; }) => void +>x : { m: boolean; } + +// Should fail under --noPropertyAccessFromIndexSignature +console.log(x.z); +>console.log(x.z) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>x.z : any +>x : { m: boolean; } +>z : any + +const m: boolean = x.m; +>m : boolean +>x.m : boolean +>x : { m: boolean; } +>m : boolean + +// Should be 'm' +type M = keyof typeof x; +>M : "m" +>x : { m: boolean; } + +// Should be able to detect a failure here +const x2 = { +>x2 : { m: true; s: string; } +>{ m: true, s: "false"} satisfies Facts : { m: true; s: string; } +>{ m: true, s: "false"} : { m: true; s: string; } + + m: true, +>m : true +>true : true + + s: "false" +>s : string +>"false" : "false" + +} satisfies Facts; + diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).errors.txt b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).errors.txt new file mode 100644 index 0000000000000..fd603a7727578 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).errors.txt @@ -0,0 +1,34 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts(13,15): error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts(22,5): error TS2322: Type 'string' is not assignable to type 'boolean'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts (2 errors) ==== + type Facts = { [key: string]: boolean }; + declare function checkTruths(x: Facts): void; + declare function checkM(x: { m: boolean }): void; + const x = { + m: true + }; + + // Should be OK + checkTruths(x); + // Should be OK + checkM(x); + // Should fail under --noPropertyAccessFromIndexSignature + console.log(x.z); + ~ +!!! error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. + const m: boolean = x.m; + + // Should be 'm' + type M = keyof typeof x; + + // Should be able to detect a failure here + const x2 = { + m: true, + s: "false" + ~ +!!! error TS2322: Type 'string' is not assignable to type 'boolean'. +!!! related TS6501 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts:1:16: The expected type comes from this index signature. + } satisfies Facts; + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).js b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).js new file mode 100644 index 0000000000000..f0afe57b996ee --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).js @@ -0,0 +1,42 @@ +//// [typeSatisfaction_propertyValueConformance1.ts] +type Facts = { [key: string]: boolean }; +declare function checkTruths(x: Facts): void; +declare function checkM(x: { m: boolean }): void; +const x = { + m: true +}; + +// Should be OK +checkTruths(x); +// Should be OK +checkM(x); +// Should fail under --noPropertyAccessFromIndexSignature +console.log(x.z); +const m: boolean = x.m; + +// Should be 'm' +type M = keyof typeof x; + +// Should be able to detect a failure here +const x2 = { + m: true, + s: "false" +} satisfies Facts; + + +//// [typeSatisfaction_propertyValueConformance1.js] +var x = { + m: true +}; +// Should be OK +checkTruths(x); +// Should be OK +checkM(x); +// Should fail under --noPropertyAccessFromIndexSignature +console.log(x.z); +var m = x.m; +// Should be able to detect a failure here +var x2 = { + m: true, + s: "false" +}; diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).symbols b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).symbols new file mode 100644 index 0000000000000..640357f878186 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).symbols @@ -0,0 +1,64 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts === +type Facts = { [key: string]: boolean }; +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 0)) +>key : Symbol(key, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 16)) + +declare function checkTruths(x: Facts): void; +>checkTruths : Symbol(checkTruths, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 40)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 1, 29)) +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 0)) + +declare function checkM(x: { m: boolean }): void; +>checkM : Symbol(checkM, Decl(typeSatisfaction_propertyValueConformance1.ts, 1, 45)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 2, 24)) +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 2, 28)) + +const x = { +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) + + m: true +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 11)) + +}; + +// Should be OK +checkTruths(x); +>checkTruths : Symbol(checkTruths, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 40)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) + +// Should be OK +checkM(x); +>checkM : Symbol(checkM, Decl(typeSatisfaction_propertyValueConformance1.ts, 1, 45)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) + +// Should fail under --noPropertyAccessFromIndexSignature +console.log(x.z); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) + +const m: boolean = x.m; +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 13, 5)) +>x.m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 11)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 11)) + +// Should be 'm' +type M = keyof typeof x; +>M : Symbol(M, Decl(typeSatisfaction_propertyValueConformance1.ts, 13, 23)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance1.ts, 3, 5)) + +// Should be able to detect a failure here +const x2 = { +>x2 : Symbol(x2, Decl(typeSatisfaction_propertyValueConformance1.ts, 19, 5)) + + m: true, +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance1.ts, 19, 12)) + + s: "false" +>s : Symbol(s, Decl(typeSatisfaction_propertyValueConformance1.ts, 20, 12)) + +} satisfies Facts; +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance1.ts, 0, 0)) + diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).types b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).types new file mode 100644 index 0000000000000..718224c6f5d1d --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance1(nopropertyaccessfromindexsignature=true).types @@ -0,0 +1,73 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts === +type Facts = { [key: string]: boolean }; +>Facts : Facts +>key : string + +declare function checkTruths(x: Facts): void; +>checkTruths : (x: Facts) => void +>x : Facts + +declare function checkM(x: { m: boolean }): void; +>checkM : (x: { m: boolean;}) => void +>x : { m: boolean; } +>m : boolean + +const x = { +>x : { m: boolean; } +>{ m: true} : { m: boolean; } + + m: true +>m : boolean +>true : true + +}; + +// Should be OK +checkTruths(x); +>checkTruths(x) : void +>checkTruths : (x: Facts) => void +>x : { m: boolean; } + +// Should be OK +checkM(x); +>checkM(x) : void +>checkM : (x: { m: boolean; }) => void +>x : { m: boolean; } + +// Should fail under --noPropertyAccessFromIndexSignature +console.log(x.z); +>console.log(x.z) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>x.z : any +>x : { m: boolean; } +>z : any + +const m: boolean = x.m; +>m : boolean +>x.m : boolean +>x : { m: boolean; } +>m : boolean + +// Should be 'm' +type M = keyof typeof x; +>M : "m" +>x : { m: boolean; } + +// Should be able to detect a failure here +const x2 = { +>x2 : { m: true; s: string; } +>{ m: true, s: "false"} satisfies Facts : { m: true; s: string; } +>{ m: true, s: "false"} : { m: true; s: string; } + + m: true, +>m : true +>true : true + + s: "false" +>s : string +>"false" : "false" + +} satisfies Facts; + diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).errors.txt b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).errors.txt new file mode 100644 index 0000000000000..57f58d646f60e --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).errors.txt @@ -0,0 +1,34 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts(12,15): error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts(22,5): error TS2322: Type 'string' is not assignable to type 'boolean'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts (2 errors) ==== + type Facts = { [key: string]: boolean }; + declare function checkTruths(x: Facts): void; + declare function checkM(x: { m: boolean }): void; + const x = { + m: true + }; + + // Should be OK + checkTruths(x); + // Should be OK + checkM(x); + console.log(x.z); + ~ +!!! error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. + // Should be OK under --noUncheckedIndexedAccess + const m: boolean = x.m; + + // Should be 'm' + type M = keyof typeof x; + + // Should be able to detect a failure here + const x2 = { + m: true, + s: "false" + ~ +!!! error TS2322: Type 'string' is not assignable to type 'boolean'. +!!! related TS6501 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts:1:16: The expected type comes from this index signature. + } satisfies Facts; + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).js b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).js new file mode 100644 index 0000000000000..450bf97193f95 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).js @@ -0,0 +1,42 @@ +//// [typeSatisfaction_propertyValueConformance2.ts] +type Facts = { [key: string]: boolean }; +declare function checkTruths(x: Facts): void; +declare function checkM(x: { m: boolean }): void; +const x = { + m: true +}; + +// Should be OK +checkTruths(x); +// Should be OK +checkM(x); +console.log(x.z); +// Should be OK under --noUncheckedIndexedAccess +const m: boolean = x.m; + +// Should be 'm' +type M = keyof typeof x; + +// Should be able to detect a failure here +const x2 = { + m: true, + s: "false" +} satisfies Facts; + + +//// [typeSatisfaction_propertyValueConformance2.js] +var x = { + m: true +}; +// Should be OK +checkTruths(x); +// Should be OK +checkM(x); +console.log(x.z); +// Should be OK under --noUncheckedIndexedAccess +var m = x.m; +// Should be able to detect a failure here +var x2 = { + m: true, + s: "false" +}; diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).symbols b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).symbols new file mode 100644 index 0000000000000..d2526bf40f2df --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).symbols @@ -0,0 +1,64 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts === +type Facts = { [key: string]: boolean }; +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 0)) +>key : Symbol(key, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 16)) + +declare function checkTruths(x: Facts): void; +>checkTruths : Symbol(checkTruths, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 40)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 1, 29)) +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 0)) + +declare function checkM(x: { m: boolean }): void; +>checkM : Symbol(checkM, Decl(typeSatisfaction_propertyValueConformance2.ts, 1, 45)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 2, 24)) +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 2, 28)) + +const x = { +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) + + m: true +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 11)) + +}; + +// Should be OK +checkTruths(x); +>checkTruths : Symbol(checkTruths, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 40)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) + +// Should be OK +checkM(x); +>checkM : Symbol(checkM, Decl(typeSatisfaction_propertyValueConformance2.ts, 1, 45)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) + +console.log(x.z); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) + +// Should be OK under --noUncheckedIndexedAccess +const m: boolean = x.m; +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 13, 5)) +>x.m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 11)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 11)) + +// Should be 'm' +type M = keyof typeof x; +>M : Symbol(M, Decl(typeSatisfaction_propertyValueConformance2.ts, 13, 23)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) + +// Should be able to detect a failure here +const x2 = { +>x2 : Symbol(x2, Decl(typeSatisfaction_propertyValueConformance2.ts, 19, 5)) + + m: true, +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 19, 12)) + + s: "false" +>s : Symbol(s, Decl(typeSatisfaction_propertyValueConformance2.ts, 20, 12)) + +} satisfies Facts; +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 0)) + diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).types b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).types new file mode 100644 index 0000000000000..a707728a1a6b0 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=false).types @@ -0,0 +1,73 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts === +type Facts = { [key: string]: boolean }; +>Facts : Facts +>key : string + +declare function checkTruths(x: Facts): void; +>checkTruths : (x: Facts) => void +>x : Facts + +declare function checkM(x: { m: boolean }): void; +>checkM : (x: { m: boolean;}) => void +>x : { m: boolean; } +>m : boolean + +const x = { +>x : { m: boolean; } +>{ m: true} : { m: boolean; } + + m: true +>m : boolean +>true : true + +}; + +// Should be OK +checkTruths(x); +>checkTruths(x) : void +>checkTruths : (x: Facts) => void +>x : { m: boolean; } + +// Should be OK +checkM(x); +>checkM(x) : void +>checkM : (x: { m: boolean; }) => void +>x : { m: boolean; } + +console.log(x.z); +>console.log(x.z) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>x.z : any +>x : { m: boolean; } +>z : any + +// Should be OK under --noUncheckedIndexedAccess +const m: boolean = x.m; +>m : boolean +>x.m : boolean +>x : { m: boolean; } +>m : boolean + +// Should be 'm' +type M = keyof typeof x; +>M : "m" +>x : { m: boolean; } + +// Should be able to detect a failure here +const x2 = { +>x2 : { m: true; s: string; } +>{ m: true, s: "false"} satisfies Facts : { m: true; s: string; } +>{ m: true, s: "false"} : { m: true; s: string; } + + m: true, +>m : true +>true : true + + s: "false" +>s : string +>"false" : "false" + +} satisfies Facts; + diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).errors.txt b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).errors.txt new file mode 100644 index 0000000000000..57f58d646f60e --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).errors.txt @@ -0,0 +1,34 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts(12,15): error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts(22,5): error TS2322: Type 'string' is not assignable to type 'boolean'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts (2 errors) ==== + type Facts = { [key: string]: boolean }; + declare function checkTruths(x: Facts): void; + declare function checkM(x: { m: boolean }): void; + const x = { + m: true + }; + + // Should be OK + checkTruths(x); + // Should be OK + checkM(x); + console.log(x.z); + ~ +!!! error TS2339: Property 'z' does not exist on type '{ m: boolean; }'. + // Should be OK under --noUncheckedIndexedAccess + const m: boolean = x.m; + + // Should be 'm' + type M = keyof typeof x; + + // Should be able to detect a failure here + const x2 = { + m: true, + s: "false" + ~ +!!! error TS2322: Type 'string' is not assignable to type 'boolean'. +!!! related TS6501 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts:1:16: The expected type comes from this index signature. + } satisfies Facts; + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).js b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).js new file mode 100644 index 0000000000000..450bf97193f95 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).js @@ -0,0 +1,42 @@ +//// [typeSatisfaction_propertyValueConformance2.ts] +type Facts = { [key: string]: boolean }; +declare function checkTruths(x: Facts): void; +declare function checkM(x: { m: boolean }): void; +const x = { + m: true +}; + +// Should be OK +checkTruths(x); +// Should be OK +checkM(x); +console.log(x.z); +// Should be OK under --noUncheckedIndexedAccess +const m: boolean = x.m; + +// Should be 'm' +type M = keyof typeof x; + +// Should be able to detect a failure here +const x2 = { + m: true, + s: "false" +} satisfies Facts; + + +//// [typeSatisfaction_propertyValueConformance2.js] +var x = { + m: true +}; +// Should be OK +checkTruths(x); +// Should be OK +checkM(x); +console.log(x.z); +// Should be OK under --noUncheckedIndexedAccess +var m = x.m; +// Should be able to detect a failure here +var x2 = { + m: true, + s: "false" +}; diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).symbols b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).symbols new file mode 100644 index 0000000000000..d2526bf40f2df --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).symbols @@ -0,0 +1,64 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts === +type Facts = { [key: string]: boolean }; +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 0)) +>key : Symbol(key, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 16)) + +declare function checkTruths(x: Facts): void; +>checkTruths : Symbol(checkTruths, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 40)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 1, 29)) +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 0)) + +declare function checkM(x: { m: boolean }): void; +>checkM : Symbol(checkM, Decl(typeSatisfaction_propertyValueConformance2.ts, 1, 45)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 2, 24)) +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 2, 28)) + +const x = { +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) + + m: true +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 11)) + +}; + +// Should be OK +checkTruths(x); +>checkTruths : Symbol(checkTruths, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 40)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) + +// Should be OK +checkM(x); +>checkM : Symbol(checkM, Decl(typeSatisfaction_propertyValueConformance2.ts, 1, 45)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) + +console.log(x.z); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) + +// Should be OK under --noUncheckedIndexedAccess +const m: boolean = x.m; +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 13, 5)) +>x.m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 11)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 11)) + +// Should be 'm' +type M = keyof typeof x; +>M : Symbol(M, Decl(typeSatisfaction_propertyValueConformance2.ts, 13, 23)) +>x : Symbol(x, Decl(typeSatisfaction_propertyValueConformance2.ts, 3, 5)) + +// Should be able to detect a failure here +const x2 = { +>x2 : Symbol(x2, Decl(typeSatisfaction_propertyValueConformance2.ts, 19, 5)) + + m: true, +>m : Symbol(m, Decl(typeSatisfaction_propertyValueConformance2.ts, 19, 12)) + + s: "false" +>s : Symbol(s, Decl(typeSatisfaction_propertyValueConformance2.ts, 20, 12)) + +} satisfies Facts; +>Facts : Symbol(Facts, Decl(typeSatisfaction_propertyValueConformance2.ts, 0, 0)) + diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).types b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).types new file mode 100644 index 0000000000000..a707728a1a6b0 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance2(nouncheckedindexedaccess=true).types @@ -0,0 +1,73 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts === +type Facts = { [key: string]: boolean }; +>Facts : Facts +>key : string + +declare function checkTruths(x: Facts): void; +>checkTruths : (x: Facts) => void +>x : Facts + +declare function checkM(x: { m: boolean }): void; +>checkM : (x: { m: boolean;}) => void +>x : { m: boolean; } +>m : boolean + +const x = { +>x : { m: boolean; } +>{ m: true} : { m: boolean; } + + m: true +>m : boolean +>true : true + +}; + +// Should be OK +checkTruths(x); +>checkTruths(x) : void +>checkTruths : (x: Facts) => void +>x : { m: boolean; } + +// Should be OK +checkM(x); +>checkM(x) : void +>checkM : (x: { m: boolean; }) => void +>x : { m: boolean; } + +console.log(x.z); +>console.log(x.z) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>x.z : any +>x : { m: boolean; } +>z : any + +// Should be OK under --noUncheckedIndexedAccess +const m: boolean = x.m; +>m : boolean +>x.m : boolean +>x : { m: boolean; } +>m : boolean + +// Should be 'm' +type M = keyof typeof x; +>M : "m" +>x : { m: boolean; } + +// Should be able to detect a failure here +const x2 = { +>x2 : { m: true; s: string; } +>{ m: true, s: "false"} satisfies Facts : { m: true; s: string; } +>{ m: true, s: "false"} : { m: true; s: string; } + + m: true, +>m : true +>true : true + + s: "false" +>s : string +>"false" : "false" + +} satisfies Facts; + diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.errors.txt b/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.errors.txt new file mode 100644 index 0000000000000..0ae5d8fffb313 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.errors.txt @@ -0,0 +1,17 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance3.ts(6,26): error TS2322: Type '{ r: number; g: number; d: number; }' is not assignable to type 'Color'. + Object literal may only specify known properties, and 'd' does not exist in type 'Color'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance3.ts (1 errors) ==== + export type Color = { r: number, g: number, b: number }; + + // All of these should be Colors, but I only use some of them here. + export const Palette = { + white: { r: 255, g: 255, b: 255 }, + black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' + ~~~~ +!!! error TS2322: Type '{ r: number; g: number; d: number; }' is not assignable to type 'Color'. +!!! error TS2322: Object literal may only specify known properties, and 'd' does not exist in type 'Color'. + blue: { r: 0, g: 0, b: 255 }, + } satisfies Record; + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.js b/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.js new file mode 100644 index 0000000000000..c8c885e74e365 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.js @@ -0,0 +1,21 @@ +//// [typeSatisfaction_propertyValueConformance3.ts] +export type Color = { r: number, g: number, b: number }; + +// All of these should be Colors, but I only use some of them here. +export const Palette = { + white: { r: 255, g: 255, b: 255 }, + black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' + blue: { r: 0, g: 0, b: 255 }, +} satisfies Record; + + +//// [typeSatisfaction_propertyValueConformance3.js] +"use strict"; +exports.__esModule = true; +exports.Palette = void 0; +// All of these should be Colors, but I only use some of them here. +exports.Palette = { + white: { r: 255, g: 255, b: 255 }, + black: { r: 0, g: 0, d: 0 }, + blue: { r: 0, g: 0, b: 255 } +}; diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.symbols b/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.symbols new file mode 100644 index 0000000000000..4cbc5cf907540 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.symbols @@ -0,0 +1,33 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance3.ts === +export type Color = { r: number, g: number, b: number }; +>Color : Symbol(Color, Decl(typeSatisfaction_propertyValueConformance3.ts, 0, 0)) +>r : Symbol(r, Decl(typeSatisfaction_propertyValueConformance3.ts, 0, 21)) +>g : Symbol(g, Decl(typeSatisfaction_propertyValueConformance3.ts, 0, 32)) +>b : Symbol(b, Decl(typeSatisfaction_propertyValueConformance3.ts, 0, 43)) + +// All of these should be Colors, but I only use some of them here. +export const Palette = { +>Palette : Symbol(Palette, Decl(typeSatisfaction_propertyValueConformance3.ts, 3, 12)) + + white: { r: 255, g: 255, b: 255 }, +>white : Symbol(white, Decl(typeSatisfaction_propertyValueConformance3.ts, 3, 24)) +>r : Symbol(r, Decl(typeSatisfaction_propertyValueConformance3.ts, 4, 12)) +>g : Symbol(g, Decl(typeSatisfaction_propertyValueConformance3.ts, 4, 20)) +>b : Symbol(b, Decl(typeSatisfaction_propertyValueConformance3.ts, 4, 28)) + + black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' +>black : Symbol(black, Decl(typeSatisfaction_propertyValueConformance3.ts, 4, 38)) +>r : Symbol(r, Decl(typeSatisfaction_propertyValueConformance3.ts, 5, 12)) +>g : Symbol(g, Decl(typeSatisfaction_propertyValueConformance3.ts, 5, 18)) +>d : Symbol(d, Decl(typeSatisfaction_propertyValueConformance3.ts, 5, 24)) + + blue: { r: 0, g: 0, b: 255 }, +>blue : Symbol(blue, Decl(typeSatisfaction_propertyValueConformance3.ts, 5, 32)) +>r : Symbol(r, Decl(typeSatisfaction_propertyValueConformance3.ts, 6, 11)) +>g : Symbol(g, Decl(typeSatisfaction_propertyValueConformance3.ts, 6, 17)) +>b : Symbol(b, Decl(typeSatisfaction_propertyValueConformance3.ts, 6, 23)) + +} satisfies Record; +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>Color : Symbol(Color, Decl(typeSatisfaction_propertyValueConformance3.ts, 0, 0)) + diff --git a/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.types b/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.types new file mode 100644 index 0000000000000..56af78477d6d1 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_propertyValueConformance3.types @@ -0,0 +1,45 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance3.ts === +export type Color = { r: number, g: number, b: number }; +>Color : Color +>r : number +>g : number +>b : number + +// All of these should be Colors, but I only use some of them here. +export const Palette = { +>Palette : { white: { r: number; g: number; b: number; }; black: { r: number; g: number; d: number; }; blue: { r: number; g: number; b: number; }; } +>{ white: { r: 255, g: 255, b: 255 }, black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' blue: { r: 0, g: 0, b: 255 },} satisfies Record : { white: { r: number; g: number; b: number; }; black: { r: number; g: number; d: number; }; blue: { r: number; g: number; b: number; }; } +>{ white: { r: 255, g: 255, b: 255 }, black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' blue: { r: 0, g: 0, b: 255 },} : { white: { r: number; g: number; b: number; }; black: { r: number; g: number; d: number; }; blue: { r: number; g: number; b: number; }; } + + white: { r: 255, g: 255, b: 255 }, +>white : { r: number; g: number; b: number; } +>{ r: 255, g: 255, b: 255 } : { r: number; g: number; b: number; } +>r : number +>255 : 255 +>g : number +>255 : 255 +>b : number +>255 : 255 + + black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' +>black : { r: number; g: number; d: number; } +>{ r: 0, g: 0, d: 0 } : { r: number; g: number; d: number; } +>r : number +>0 : 0 +>g : number +>0 : 0 +>d : number +>0 : 0 + + blue: { r: 0, g: 0, b: 255 }, +>blue : { r: number; g: number; b: number; } +>{ r: 0, g: 0, b: 255 } : { r: number; g: number; b: number; } +>r : number +>0 : 0 +>g : number +>0 : 0 +>b : number +>255 : 255 + +} satisfies Record; + diff --git a/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.errors.txt b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.errors.txt new file mode 100644 index 0000000000000..9213184ec6cf6 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts(1,7): error TS2322: Type '"foo"' is not assignable to type '"baz"'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts(2,7): error TS2322: Type '{ xyz: string; }' is not assignable to type '{ xyz: "baz"; }'. + Types of property 'xyz' are incompatible. + Type 'string' is not assignable to type '"baz"'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts(2,29): error TS2322: Type 'string' is not assignable to type '"foo" | "bar"'. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts (3 errors) ==== + const a: "baz" = "foo" satisfies "foo" | "bar"; + ~ +!!! error TS2322: Type '"foo"' is not assignable to type '"baz"'. + const b: { xyz: "baz" } = { xyz: "foo" } satisfies { xyz: "foo" | "bar" }; + ~ +!!! error TS2322: Type '{ xyz: string; }' is not assignable to type '{ xyz: "baz"; }'. +!!! error TS2322: Types of property 'xyz' are incompatible. +!!! error TS2322: Type 'string' is not assignable to type '"baz"'. + ~~~ +!!! error TS2322: Type 'string' is not assignable to type '"foo" | "bar"'. +!!! related TS6500 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts:2:54: The expected type comes from property 'xyz' which is declared here on type '{ xyz: "foo" | "bar"; }' + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.js b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.js new file mode 100644 index 0000000000000..65d5dc56a40a1 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.js @@ -0,0 +1,8 @@ +//// [typeSatisfaction_vacuousIntersectionOfContextualTypes.ts] +const a: "baz" = "foo" satisfies "foo" | "bar"; +const b: { xyz: "baz" } = { xyz: "foo" } satisfies { xyz: "foo" | "bar" }; + + +//// [typeSatisfaction_vacuousIntersectionOfContextualTypes.js] +var a = "foo"; +var b = { xyz: "foo" }; diff --git a/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.symbols b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.symbols new file mode 100644 index 0000000000000..e42d85f578765 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.symbols @@ -0,0 +1,10 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts === +const a: "baz" = "foo" satisfies "foo" | "bar"; +>a : Symbol(a, Decl(typeSatisfaction_vacuousIntersectionOfContextualTypes.ts, 0, 5)) + +const b: { xyz: "baz" } = { xyz: "foo" } satisfies { xyz: "foo" | "bar" }; +>b : Symbol(b, Decl(typeSatisfaction_vacuousIntersectionOfContextualTypes.ts, 1, 5)) +>xyz : Symbol(xyz, Decl(typeSatisfaction_vacuousIntersectionOfContextualTypes.ts, 1, 10)) +>xyz : Symbol(xyz, Decl(typeSatisfaction_vacuousIntersectionOfContextualTypes.ts, 1, 27)) +>xyz : Symbol(xyz, Decl(typeSatisfaction_vacuousIntersectionOfContextualTypes.ts, 1, 52)) + diff --git a/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.types b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.types new file mode 100644 index 0000000000000..49119c4a4157e --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts === +const a: "baz" = "foo" satisfies "foo" | "bar"; +>a : "baz" +>"foo" satisfies "foo" | "bar" : "foo" +>"foo" : "foo" + +const b: { xyz: "baz" } = { xyz: "foo" } satisfies { xyz: "foo" | "bar" }; +>b : { xyz: "baz"; } +>xyz : "baz" +>{ xyz: "foo" } satisfies { xyz: "foo" | "bar" } : { xyz: string; } +>{ xyz: "foo" } : { xyz: string; } +>xyz : string +>"foo" : "foo" +>xyz : "foo" | "bar" + diff --git a/tests/cases/compiler/satisfiesScenarios.ts b/tests/cases/compiler/satisfiesScenarios.ts deleted file mode 100644 index 44f145e87af5b..0000000000000 --- a/tests/cases/compiler/satisfiesScenarios.ts +++ /dev/null @@ -1,112 +0,0 @@ - -const x = [1, 2] satisfies [number, number]; - -interface A { - a: string -} -let d = { a: 'test' } satisfies A; -let e = { a: 'test', b: 'test' } satisfies A; - -// Most examples from #47920 -namespace PropNameConstraining { - type Keys = 'a' | 'b' | 'c' | 'd'; - - const p = { - a: 0, - b: "hello", - x: 8 // Should error, 'x' isn't in 'Keys' - } satisfies Partial>; - - // Should be OK -- retain info that a is number and b is string - let a = p.a.toFixed(); - let b = p.b.substring(1); - // Should error even though 'd' is in 'Keys' - let d = p.d; -} - -namespace PropertyNameFulfillment { - type Keys = 'a' | 'b' | 'c' | 'd'; - - const p = { - a: 0, - b: "hello", - x: 8 // Should error, 'x' isn't in 'Keys' - } satisfies Record; - - // Should be OK -- retain info that a is number and b is string - let a = p.a.toFixed(); - let b = p.b.substr(1); - // Should error even though 'd' is in 'Keys' - let d = p.d; -} - -namespace PropertyValueConformance { - type Facts = { [key: string]: boolean }; - declare function checkTruths(x: Facts): void; - declare function checkM(x: { m: boolean }): void; - const x = { - m: true - }; - - // Should be OK - checkTruths(x); - // Should be OK - checkM(x); - // Should fail under --noIndexSignaturePropertyAccess - console.log(x.z); - // Should be OK under --noUncheckedIndexedAccess - const m: boolean = x.m; - - // Should be 'm' - type M = keyof typeof x; - - // Should be able to detect a failure here - const x2 = { - m: true, - s: "false" - } satisfies Facts; -} - -namespace PropertyValueConformance2 { - export type Color = { r: number, g: number, b: number }; - - // All of these should be Colors, but I only use some of them here. - export const Palette = { - white: { r: 255, g: 255, b: 255 }, - black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' - blue: { r: 0, g: 0, b: 255 }, - } satisfies Record; -} - -namespace EnsureInterfaceImpl { - type Movable = { - move(distance: number): void; - }; - - const car = { - start() { }, - move(d) { - // d should be number - }, - stop() { } - } satisfies Movable & Record; -} - -namespace OptionalMemberConformance { - type Point2d = { x: number, y: number }; - // Undesirable behavior today with type annotation - const a = { x: 10 } satisfies Partial; - // Should OK - console.log(a.x.toFixed()); - // Should error - let p = a.y; -} - -namespace ContextualTyping { - type Predicates = { [s: string]: (n: number) => boolean }; - - const p: Predicates = { - isEven: n => n % 2 === 0, - isOdd: n => n % 2 === 1 - }; -} \ No newline at end of file diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts index fa60720e297bb..5e268ffb1e1cc 100644 --- a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction.ts @@ -8,9 +8,17 @@ type T1 = { type T2 = (x: string) => void; -const a1 = { a: 1 } satisfies I1; // Ok -const a2 = { a: 1, b: 1 } satisfies I1; // Error -const a3 = { } satisfies I1; // Error +const t1 = { a: 1 } satisfies I1; // Ok +const t2 = { a: 1, b: 1 } satisfies I1; // Error +const t3 = { } satisfies I1; // Error -const a4: T1 = { a: "a" } satisfies T1; // Ok -const a5 = (m => m.substring(0)) satisfies T2; // Ok +const t4: T1 = { a: "a" } satisfies T1; // Ok +const t5 = (m => m.substring(0)) satisfies T2; // Ok + +const t6 = [1, 2] satisfies [number, number]; + +interface A { + a: string +} +let t7 = { a: 'test' } satisfies A; +let t8 = { a: 'test', b: 'test' } satisfies A; diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping1.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping1.ts new file mode 100644 index 0000000000000..d099059d8545f --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping1.ts @@ -0,0 +1,6 @@ +type Predicates = { [s: string]: (n: number) => boolean }; + +const p = { + isEven: n => n % 2 === 0, + isOdd: n => n % 2 === 1 +} satisfies Predicates; diff --git a/tests/cases/compiler/satisfiesContextualType.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping2.ts similarity index 97% rename from tests/cases/compiler/satisfiesContextualType.ts rename to tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping2.ts index f3768efb848b9..597a1eed2bdbd 100644 --- a/tests/cases/compiler/satisfiesContextualType.ts +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping2.ts @@ -1,9 +1,9 @@ -// @strict: true - -let obj: { f(s: string): void } & Record = { - f(s) { }, // "incorrect" implicit any on 's' - g(s) { } -} satisfies { g(s: string): void } & Record; - -// This needs to not crash (outer node is not expression) -({ f(x) { } }) satisfies { f(s: string): void }; +// @strict: true + +let obj: { f(s: string): void } & Record = { + f(s) { }, // "incorrect" implicit any on 's' + g(s) { } +} satisfies { g(s: string): void } & Record; + +// This needs to not crash (outer node is not expression) +({ f(x) { } }) satisfies { f(s: string): void }; diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_ensureInterfaceImpl.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_ensureInterfaceImpl.ts new file mode 100644 index 0000000000000..a3dbaf484a8ae --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_ensureInterfaceImpl.ts @@ -0,0 +1,11 @@ +type Movable = { + move(distance: number): void; +}; + +const car = { + start() { }, + move(d) { + // d should be number + }, + stop() { } +} satisfies Movable & Record; diff --git a/tests/cases/compiler/jsFileCompilationTypeSatisfaction.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_js.ts similarity index 94% rename from tests/cases/compiler/jsFileCompilationTypeSatisfaction.ts rename to tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_js.ts index ba4701687bc08..5826e4a20971d 100644 --- a/tests/cases/compiler/jsFileCompilationTypeSatisfaction.ts +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_js.ts @@ -1,5 +1,5 @@ -// @allowJs: true -// @filename: /src/a.js -// @out: /lib/a.js - -var v = undefined satisfies 1; +// @allowJs: true +// @filename: /src/a.js +// @out: /lib/a.js + +var v = undefined satisfies 1; diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_optionalMemberConformance.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_optionalMemberConformance.ts new file mode 100644 index 0000000000000..939c6fc60a688 --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_optionalMemberConformance.ts @@ -0,0 +1,7 @@ +type Point2d = { x: number, y: number }; +// Undesirable behavior today with type annotation +const a = { x: 10 } satisfies Partial; +// Should OK +console.log(a.x.toFixed()); +// Should error +let p = a.y; diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propNameConstraining.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propNameConstraining.ts new file mode 100644 index 0000000000000..4745de6e77dcb --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propNameConstraining.ts @@ -0,0 +1,13 @@ +type Keys = 'a' | 'b' | 'c' | 'd'; + +const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' +} satisfies Partial>; + +// Should be OK -- retain info that a is number and b is string +let a = p.a.toFixed(); +let b = p.b.substring(1); +// Should error even though 'd' is in 'Keys' +let d = p.d; diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyNameFulfillment.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyNameFulfillment.ts new file mode 100644 index 0000000000000..e344bcfbff24d --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyNameFulfillment.ts @@ -0,0 +1,13 @@ +type Keys = 'a' | 'b' | 'c' | 'd'; + +const p = { + a: 0, + b: "hello", + x: 8 // Should error, 'x' isn't in 'Keys' +} satisfies Record; + +// Should be OK -- retain info that a is number and b is string +let a = p.a.toFixed(); +let b = p.b.substring(1); +// Should error even though 'd' is in 'Keys' +let d = p.d; diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts new file mode 100644 index 0000000000000..62a51f2ac7102 --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance1.ts @@ -0,0 +1,25 @@ +// @noPropertyAccessFromIndexSignature: true, false + +type Facts = { [key: string]: boolean }; +declare function checkTruths(x: Facts): void; +declare function checkM(x: { m: boolean }): void; +const x = { + m: true +}; + +// Should be OK +checkTruths(x); +// Should be OK +checkM(x); +// Should fail under --noPropertyAccessFromIndexSignature +console.log(x.z); +const m: boolean = x.m; + +// Should be 'm' +type M = keyof typeof x; + +// Should be able to detect a failure here +const x2 = { + m: true, + s: "false" +} satisfies Facts; diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts new file mode 100644 index 0000000000000..762a9b0f4e786 --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance2.ts @@ -0,0 +1,25 @@ +// @noUncheckedIndexedAccess: true, false + +type Facts = { [key: string]: boolean }; +declare function checkTruths(x: Facts): void; +declare function checkM(x: { m: boolean }): void; +const x = { + m: true +}; + +// Should be OK +checkTruths(x); +// Should be OK +checkM(x); +console.log(x.z); +// Should be OK under --noUncheckedIndexedAccess +const m: boolean = x.m; + +// Should be 'm' +type M = keyof typeof x; + +// Should be able to detect a failure here +const x2 = { + m: true, + s: "false" +} satisfies Facts; diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance3.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance3.ts new file mode 100644 index 0000000000000..178da1c2c438a --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_propertyValueConformance3.ts @@ -0,0 +1,8 @@ +export type Color = { r: number, g: number, b: number }; + +// All of these should be Colors, but I only use some of them here. +export const Palette = { + white: { r: 255, g: 255, b: 255 }, + black: { r: 0, g: 0, d: 0 }, // <- oops! 'd' in place of 'b' + blue: { r: 0, g: 0, b: 255 }, +} satisfies Record; diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts new file mode 100644 index 0000000000000..92af1c521b207 --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts @@ -0,0 +1,2 @@ +const a: "baz" = "foo" satisfies "foo" | "bar"; +const b: { xyz: "baz" } = { xyz: "foo" } satisfies { xyz: "foo" | "bar" }; From 834c1f9b00dcde72d499c86a2af3570e9d305834 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Tue, 14 Jun 2022 21:33:55 +0300 Subject: [PATCH 08/11] update baseline --- ...when-changes-happen-in-contained-node_modules-directories.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/baselines/reference/tsserver/moduleSpecifierCache/invalidates-module-specifiers-when-changes-happen-in-contained-node_modules-directories.js b/tests/baselines/reference/tsserver/moduleSpecifierCache/invalidates-module-specifiers-when-changes-happen-in-contained-node_modules-directories.js index a5365671bef02..0980d5d06cb46 100644 --- a/tests/baselines/reference/tsserver/moduleSpecifierCache/invalidates-module-specifiers-when-changes-happen-in-contained-node_modules-directories.js +++ b/tests/baselines/reference/tsserver/moduleSpecifierCache/invalidates-module-specifiers-when-changes-happen-in-contained-node_modules-directories.js @@ -128,7 +128,7 @@ collectAutoImports: response is incomplete collectAutoImports: * getCompletionData: Semantic work: * getCompletionsAtPosition: getCompletionEntriesFromSymbols: * -response:{"response":{"flags":1,"isGlobalCompletion":true,"isMemberCompletion":false,"isNewIdentifierLocation":false,"optionalReplacementSpan":{"start":{"line":1,"offset":1},"end":{"line":1,"offset":4}},"entries":[{"name":"abstract","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"any","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"as","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"asserts","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"async","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"await","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"bigint","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"boolean","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"break","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"case","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"catch","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"class","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"const","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"continue","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"debugger","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"declare","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"default","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"delete","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"do","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"else","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"enum","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"export","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"extends","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"false","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"finally","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"for","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"function","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"globalThis","kind":"module","kindModifiers":"","sortText":"15"},{"name":"if","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"implements","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"import","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"in","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"infer","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"instanceof","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"interface","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"keyof","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"let","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"module","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"namespace","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"never","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"new","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"null","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"number","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"object","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"package","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"readonly","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"return","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"string","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"super","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"switch","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"symbol","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"this","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"throw","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"true","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"try","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"type","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"typeof","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"undefined","kind":"var","kindModifiers":"","sortText":"15"},{"name":"unique","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"unknown","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"var","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"void","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"while","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"with","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"yield","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"foo","kind":"const","kindModifiers":"export","sortText":"16","hasAction":true,"source":"/src/a","data":{"exportName":"foo","exportMapKey":"foo|*|","fileName":"/src/a.ts"}}]},"responseRequired":true} +response:{"response":{"flags":1,"isGlobalCompletion":true,"isMemberCompletion":false,"isNewIdentifierLocation":false,"optionalReplacementSpan":{"start":{"line":1,"offset":1},"end":{"line":1,"offset":4}},"entries":[{"name":"abstract","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"any","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"as","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"asserts","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"async","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"await","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"bigint","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"boolean","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"break","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"case","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"catch","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"class","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"const","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"continue","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"debugger","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"declare","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"default","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"delete","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"do","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"else","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"enum","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"export","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"extends","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"false","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"finally","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"for","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"function","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"globalThis","kind":"module","kindModifiers":"","sortText":"15"},{"name":"if","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"implements","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"import","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"in","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"infer","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"instanceof","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"interface","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"keyof","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"let","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"module","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"namespace","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"never","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"new","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"null","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"number","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"object","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"package","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"readonly","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"return","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"satisfies","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"string","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"super","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"switch","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"symbol","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"this","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"throw","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"true","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"try","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"type","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"typeof","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"undefined","kind":"var","kindModifiers":"","sortText":"15"},{"name":"unique","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"unknown","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"var","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"void","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"while","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"with","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"yield","kind":"keyword","kindModifiers":"","sortText":"15"},{"name":"foo","kind":"const","kindModifiers":"export","sortText":"16","hasAction":true,"source":"/src/a","data":{"exportName":"foo","exportMapKey":"foo|*|","fileName":"/src/a.ts"}}]},"responseRequired":true} request:{"seq":0,"type":"request","command":"completionInfo","arguments":{"file":"/src/c.ts","line":1,"offset":8}} getCompletionData: Get current token: * getCompletionData: Is inside comment: * From a243eb66fc4be7222f51801395281aaf3cb68979 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Sat, 23 Jul 2022 05:23:47 +0300 Subject: [PATCH 09/11] add missing contextFlags argument --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6181f176b8adf..e754a5e307814 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27403,7 +27403,7 @@ namespace ts { return getContextualType(parent as NonNullExpression, contextFlags); case SyntaxKind.SatisfiesExpression: const assertedType = getTypeFromTypeNode((parent as SatisfiesExpression).type); - const outerType = getContextualType(parent as SatisfiesExpression); + const outerType = getContextualType(parent as SatisfiesExpression, contextFlags); return outerType === undefined ? assertedType : getIntersectionType([assertedType, outerType]); case SyntaxKind.ExportAssignment: return tryGetTypeFromEffectiveTypeNode(parent as ExportAssignment); From 66d7ca06d1a8962296f1fa66fdcc0387e66b7da4 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Thu, 25 Aug 2022 21:46:04 +0300 Subject: [PATCH 10/11] use asserted type --- src/compiler/checker.ts | 4 +--- src/compiler/parser.ts | 2 +- .../typeSatisfaction_contextualTyping2.types | 8 ++++---- ...vacuousIntersectionOfContextualTypes.errors.txt | 14 +++++--------- ...tion_vacuousIntersectionOfContextualTypes.types | 6 +++--- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e2642f83d830c..7bd766f2b8d5d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27506,9 +27506,7 @@ namespace ts { case SyntaxKind.NonNullExpression: return getContextualType(parent as NonNullExpression, contextFlags); case SyntaxKind.SatisfiesExpression: - const assertedType = getTypeFromTypeNode((parent as SatisfiesExpression).type); - const outerType = getContextualType(parent as SatisfiesExpression, contextFlags); - return outerType === undefined ? assertedType : getIntersectionType([assertedType, outerType]); + return getTypeFromTypeNode((parent as SatisfiesExpression).type); case SyntaxKind.ExportAssignment: return tryGetTypeFromEffectiveTypeNode(parent as ExportAssignment); case SyntaxKind.JsxExpression: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6199bc1c841b4..faab2b0620326 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -394,7 +394,7 @@ namespace ts { return visitNode(cbNode, node.expression); }, [SyntaxKind.SatisfiesExpression]: function forEachChildInSatisfiesExpression(node: SatisfiesExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type) + return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type); }, [SyntaxKind.MetaProperty]: function forEachChildInMetaProperty(node: MetaProperty, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name); diff --git a/tests/baselines/reference/typeSatisfaction_contextualTyping2.types b/tests/baselines/reference/typeSatisfaction_contextualTyping2.types index 9d9e83d09c5ed..a23bf1ee8d80f 100644 --- a/tests/baselines/reference/typeSatisfaction_contextualTyping2.types +++ b/tests/baselines/reference/typeSatisfaction_contextualTyping2.types @@ -3,12 +3,12 @@ let obj: { f(s: string): void } & Record = { >obj : { f(s: string): void; } & Record >f : (s: string) => void >s : string ->{ f(s) { }, // "incorrect" implicit any on 's' g(s) { }} satisfies { g(s: string): void } & Record : { f(s: string): void; g(s: string): void; } ->{ f(s) { }, // "incorrect" implicit any on 's' g(s) { }} : { f(s: string): void; g(s: string): void; } +>{ f(s) { }, // "incorrect" implicit any on 's' g(s) { }} satisfies { g(s: string): void } & Record : { f(s: any): void; g(s: string): void; } +>{ f(s) { }, // "incorrect" implicit any on 's' g(s) { }} : { f(s: any): void; g(s: string): void; } f(s) { }, // "incorrect" implicit any on 's' ->f : (s: string) => void ->s : string +>f : (s: any) => void +>s : any g(s) { } >g : (s: string) => void diff --git a/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.errors.txt b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.errors.txt index 9213184ec6cf6..5145035e8159f 100644 --- a/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.errors.txt +++ b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.errors.txt @@ -1,20 +1,16 @@ tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts(1,7): error TS2322: Type '"foo"' is not assignable to type '"baz"'. -tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts(2,7): error TS2322: Type '{ xyz: string; }' is not assignable to type '{ xyz: "baz"; }'. +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts(2,7): error TS2322: Type '{ xyz: "foo"; }' is not assignable to type '{ xyz: "baz"; }'. Types of property 'xyz' are incompatible. - Type 'string' is not assignable to type '"baz"'. -tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts(2,29): error TS2322: Type 'string' is not assignable to type '"foo" | "bar"'. + Type '"foo"' is not assignable to type '"baz"'. -==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts (3 errors) ==== +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts (2 errors) ==== const a: "baz" = "foo" satisfies "foo" | "bar"; ~ !!! error TS2322: Type '"foo"' is not assignable to type '"baz"'. const b: { xyz: "baz" } = { xyz: "foo" } satisfies { xyz: "foo" | "bar" }; ~ -!!! error TS2322: Type '{ xyz: string; }' is not assignable to type '{ xyz: "baz"; }'. +!!! error TS2322: Type '{ xyz: "foo"; }' is not assignable to type '{ xyz: "baz"; }'. !!! error TS2322: Types of property 'xyz' are incompatible. -!!! error TS2322: Type 'string' is not assignable to type '"baz"'. - ~~~ -!!! error TS2322: Type 'string' is not assignable to type '"foo" | "bar"'. -!!! related TS6500 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_vacuousIntersectionOfContextualTypes.ts:2:54: The expected type comes from property 'xyz' which is declared here on type '{ xyz: "foo" | "bar"; }' +!!! error TS2322: Type '"foo"' is not assignable to type '"baz"'. \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.types b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.types index 49119c4a4157e..5b574cf380eda 100644 --- a/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.types +++ b/tests/baselines/reference/typeSatisfaction_vacuousIntersectionOfContextualTypes.types @@ -7,9 +7,9 @@ const a: "baz" = "foo" satisfies "foo" | "bar"; const b: { xyz: "baz" } = { xyz: "foo" } satisfies { xyz: "foo" | "bar" }; >b : { xyz: "baz"; } >xyz : "baz" ->{ xyz: "foo" } satisfies { xyz: "foo" | "bar" } : { xyz: string; } ->{ xyz: "foo" } : { xyz: string; } ->xyz : string +>{ xyz: "foo" } satisfies { xyz: "foo" | "bar" } : { xyz: "foo"; } +>{ xyz: "foo" } : { xyz: "foo"; } +>xyz : "foo" >"foo" : "foo" >xyz : "foo" | "bar" From a73f1c7ce4b97bf13e6c3f2341412b0216d92933 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Thu, 25 Aug 2022 22:38:18 +0300 Subject: [PATCH 11/11] accept baseline --- .../typeSatisfaction_contextualTyping2.errors.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/baselines/reference/typeSatisfaction_contextualTyping2.errors.txt diff --git a/tests/baselines/reference/typeSatisfaction_contextualTyping2.errors.txt b/tests/baselines/reference/typeSatisfaction_contextualTyping2.errors.txt new file mode 100644 index 0000000000000..2014bb3930a1a --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_contextualTyping2.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping2.ts(2,7): error TS7006: Parameter 's' implicitly has an 'any' type. + + +==== tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_contextualTyping2.ts (1 errors) ==== + let obj: { f(s: string): void } & Record = { + f(s) { }, // "incorrect" implicit any on 's' + ~ +!!! error TS7006: Parameter 's' implicitly has an 'any' type. + g(s) { } + } satisfies { g(s: string): void } & Record; + + // This needs to not crash (outer node is not expression) + ({ f(x) { } }) satisfies { f(s: string): void }; + \ No newline at end of file