From ca0e616872110b2d5e9674e0c827fc68825381d9 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Sat, 5 Feb 2022 21:04:16 +0200 Subject: [PATCH] feat(14417): add optionality to accessors --- src/compiler/binder.ts | 4 +-- src/compiler/checker.ts | 13 ++++++---- src/compiler/emitter.ts | 1 + src/compiler/factory/nodeFactory.ts | 23 +++++++++++----- src/compiler/parser.ts | 5 ++-- src/compiler/transformers/declarations.ts | 2 ++ src/compiler/transformers/es2015.ts | 4 +-- src/compiler/transformers/es2018.ts | 2 ++ src/compiler/transformers/ts.ts | 2 ++ src/compiler/types.ts | 8 +++--- src/compiler/utilities.ts | 2 ++ src/compiler/visitorPublic.ts | 2 ++ src/services/codefixes/generateAccessors.ts | 2 ++ src/services/codefixes/helpers.ts | 2 ++ .../reference/api/tsserverlibrary.d.ts | 16 ++++++------ tests/baselines/reference/api/typescript.d.ts | 16 ++++++------ .../reference/optionalAccessor1.errors.txt | 14 ++++++++++ .../baselines/reference/optionalAccessor1.js | 12 +++++++++ .../reference/optionalAccessor1.symbols | 12 +++++++++ .../reference/optionalAccessor1.types | 14 ++++++++++ .../baselines/reference/optionalAccessor2.js | 15 +++++++++++ .../reference/optionalAccessor2.symbols | 16 ++++++++++++ .../reference/optionalAccessor2.types | 17 ++++++++++++ .../baselines/reference/optionalAccessor3.js | 12 +++++++++ .../reference/optionalAccessor3.symbols | 16 ++++++++++++ .../reference/optionalAccessor3.types | 13 ++++++++++ .../baselines/reference/optionalAccessor4.js | 16 ++++++++++++ .../reference/optionalAccessor4.symbols | 16 ++++++++++++ .../reference/optionalAccessor4.types | 17 ++++++++++++ .../baselines/reference/optionalAccessor5.js | 10 +++++++ .../reference/optionalAccessor5.symbols | 8 ++++++ .../reference/optionalAccessor5.types | 8 ++++++ .../baselines/reference/optionalAccessor6.js | 19 ++++++++++++++ .../reference/optionalAccessor6.symbols | 12 +++++++++ .../reference/optionalAccessor6.types | 13 ++++++++++ .../baselines/reference/optionalAccessor7.js | 21 +++++++++++++++ .../reference/optionalAccessor7.symbols | 24 +++++++++++++++++ .../reference/optionalAccessor7.types | 26 +++++++++++++++++++ ...ssor8(exactoptionalpropertytypes=false).js | 19 ++++++++++++++ ...(exactoptionalpropertytypes=false).symbols | 24 +++++++++++++++++ ...r8(exactoptionalpropertytypes=false).types | 24 +++++++++++++++++ ...xactoptionalpropertytypes=true).errors.txt | 23 ++++++++++++++++ ...essor8(exactoptionalpropertytypes=true).js | 19 ++++++++++++++ ...8(exactoptionalpropertytypes=true).symbols | 24 +++++++++++++++++ ...or8(exactoptionalpropertytypes=true).types | 24 +++++++++++++++++ .../types/namedTypes/optionalAccessor1.ts | 6 +++++ .../types/namedTypes/optionalAccessor2.ts | 8 ++++++ .../types/namedTypes/optionalAccessor3.ts | 8 ++++++ .../types/namedTypes/optionalAccessor4.ts | 9 +++++++ .../types/namedTypes/optionalAccessor5.ts | 5 ++++ .../types/namedTypes/optionalAccessor6.ts | 7 +++++ .../types/namedTypes/optionalAccessor7.ts | 11 ++++++++ .../types/namedTypes/optionalAccessor8.ts | 14 ++++++++++ 53 files changed, 623 insertions(+), 37 deletions(-) create mode 100644 tests/baselines/reference/optionalAccessor1.errors.txt create mode 100644 tests/baselines/reference/optionalAccessor1.js create mode 100644 tests/baselines/reference/optionalAccessor1.symbols create mode 100644 tests/baselines/reference/optionalAccessor1.types create mode 100644 tests/baselines/reference/optionalAccessor2.js create mode 100644 tests/baselines/reference/optionalAccessor2.symbols create mode 100644 tests/baselines/reference/optionalAccessor2.types create mode 100644 tests/baselines/reference/optionalAccessor3.js create mode 100644 tests/baselines/reference/optionalAccessor3.symbols create mode 100644 tests/baselines/reference/optionalAccessor3.types create mode 100644 tests/baselines/reference/optionalAccessor4.js create mode 100644 tests/baselines/reference/optionalAccessor4.symbols create mode 100644 tests/baselines/reference/optionalAccessor4.types create mode 100644 tests/baselines/reference/optionalAccessor5.js create mode 100644 tests/baselines/reference/optionalAccessor5.symbols create mode 100644 tests/baselines/reference/optionalAccessor5.types create mode 100644 tests/baselines/reference/optionalAccessor6.js create mode 100644 tests/baselines/reference/optionalAccessor6.symbols create mode 100644 tests/baselines/reference/optionalAccessor6.types create mode 100644 tests/baselines/reference/optionalAccessor7.js create mode 100644 tests/baselines/reference/optionalAccessor7.symbols create mode 100644 tests/baselines/reference/optionalAccessor7.types create mode 100644 tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).js create mode 100644 tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).symbols create mode 100644 tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).types create mode 100644 tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).errors.txt create mode 100644 tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).js create mode 100644 tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).symbols create mode 100644 tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).types create mode 100644 tests/cases/conformance/types/namedTypes/optionalAccessor1.ts create mode 100644 tests/cases/conformance/types/namedTypes/optionalAccessor2.ts create mode 100644 tests/cases/conformance/types/namedTypes/optionalAccessor3.ts create mode 100644 tests/cases/conformance/types/namedTypes/optionalAccessor4.ts create mode 100644 tests/cases/conformance/types/namedTypes/optionalAccessor5.ts create mode 100644 tests/cases/conformance/types/namedTypes/optionalAccessor6.ts create mode 100644 tests/cases/conformance/types/namedTypes/optionalAccessor7.ts create mode 100644 tests/cases/conformance/types/namedTypes/optionalAccessor8.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 1f36ffff64448..5f7c95df614b9 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2637,9 +2637,9 @@ namespace ts { case SyntaxKind.Constructor: return declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Constructor, /*symbolExcludes:*/ SymbolFlags.None); case SyntaxKind.GetAccessor: - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes); + return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.GetAccessor | ((node as GetAccessorDeclaration).questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.GetAccessorExcludes); case SyntaxKind.SetAccessor: - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes); + return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.SetAccessor | ((node as SetAccessorDeclaration).questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.SetAccessorExcludes); case SyntaxKind.FunctionType: case SyntaxKind.JSDocFunctionType: case SyntaxKind.JSDocSignature: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 840aa5e827b61..bfb2e1b30d3ff 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5709,8 +5709,8 @@ namespace ts { kind === SyntaxKind.MethodSignature ? factory.createMethodSignature(modifiers, options?.name ?? factory.createIdentifier(""), options?.questionToken, typeParameters, parameters, returnTypeNode) : kind === SyntaxKind.MethodDeclaration ? factory.createMethodDeclaration(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, options?.name ?? factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) : kind === SyntaxKind.Constructor ? factory.createConstructorDeclaration(/*decorators*/ undefined, modifiers, parameters, /*body*/ undefined) : - kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) : - kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*body*/ undefined) : + kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*questionToken*/ undefined, /*body*/ undefined) : + kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*questionToken*/ undefined, /*body*/ undefined) : kind === SyntaxKind.IndexSignature ? factory.createIndexSignature(/*decorators*/ undefined, modifiers, parameters, returnTypeNode) : kind === SyntaxKind.JSDocFunctionType ? factory.createJSDocFunctionType(parameters, returnTypeNode) : kind === SyntaxKind.FunctionType ? factory.createFunctionTypeNode(typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) : @@ -7787,6 +7787,7 @@ namespace ts { /*questionToken*/ undefined, isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled) )], + /*questionToken*/ undefined, /*body*/ undefined ), p.declarations?.find(isSetAccessor) || firstPropertyLikeDecl)); } @@ -7798,6 +7799,7 @@ namespace ts { name, [], isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled), + /*questionToken*/ undefined, /*body*/ undefined ), p.declarations?.find(isGetAccessor) || firstPropertyLikeDecl)); } @@ -9496,7 +9498,6 @@ namespace ts { } let type = resolveTypeOfAccessors(symbol, writing); - if (!popTypeResolution()) { type = anyType; if (noImplicitAny) { @@ -9504,7 +9505,7 @@ namespace ts { error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); } } - return type; + return type ? addOptionality(type, /*isProperty*/ true, !!(symbol.flags & SymbolFlags.Optional)) : undefined; } function resolveTypeOfAccessors(symbol: Symbol, writing = false) { @@ -43241,9 +43242,11 @@ namespace ts { currentKind = DeclarationMeaning.Method; break; case SyntaxKind.GetAccessor: + checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional); currentKind = DeclarationMeaning.GetAccessor; break; case SyntaxKind.SetAccessor: + checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional); currentKind = DeclarationMeaning.SetAccessor; break; default: @@ -43430,7 +43433,7 @@ namespace ts { if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(accessor.name)) { return grammarErrorOnNode(accessor.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); } - if (accessor.body === undefined && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) { + if (accessor.body === undefined && !hasQuestionToken(accessor) && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) { return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{"); } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index cbc1d218dc66e..5999132bcd5e5 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2108,6 +2108,7 @@ namespace ts { writeKeyword(node.kind === SyntaxKind.GetAccessor ? "get" : "set"); writeSpace(); emit(node.name); + emit(node.questionToken); emitSignatureAndBody(node, emitSignatureHead); } diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index bde236a32b069..06c6c268019e8 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -1502,9 +1502,10 @@ namespace ts { name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, + questionToken: QuestionToken | undefined, body: Block | undefined ) { - return createBaseFunctionLikeDeclaration( + const node = createBaseFunctionLikeDeclaration( SyntaxKind.GetAccessor, decorators, modifiers, @@ -1514,6 +1515,8 @@ namespace ts { type, body ); + node.questionToken = questionToken; + return node; } // @api @@ -1524,15 +1527,17 @@ namespace ts { name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, + questionToken: QuestionToken | undefined, body: Block | undefined ) { return node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.parameters !== parameters + || node.questionToken !== questionToken || node.type !== type || node.body !== body - ? updateBaseFunctionLikeDeclaration(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body), node) + ? updateBaseFunctionLikeDeclaration(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, questionToken, body), node) : node; } @@ -1542,9 +1547,10 @@ namespace ts { modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], + questionToken: QuestionToken | undefined, body: Block | undefined ) { - return createBaseFunctionLikeDeclaration( + const node = createBaseFunctionLikeDeclaration( SyntaxKind.SetAccessor, decorators, modifiers, @@ -1554,6 +1560,8 @@ namespace ts { /*type*/ undefined, body ); + node.questionToken = questionToken; + return node; } // @api @@ -1563,14 +1571,16 @@ namespace ts { modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], + questionToken: QuestionToken | undefined, body: Block | undefined ) { return node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.parameters !== parameters + || node.questionToken !== questionToken || node.body !== body - ? updateBaseFunctionLikeDeclaration(createSetAccessorDeclaration(decorators, modifiers, name, parameters, body), node) + ? updateBaseFunctionLikeDeclaration(createSetAccessorDeclaration(decorators, modifiers, name, parameters, questionToken, body), node) : node; } @@ -5755,6 +5765,7 @@ namespace ts { /*type*/ undefined, /*initializer*/ undefined )], + /*questionToken*/ undefined, createBlock([ createExpressionStatement(expression) ]) @@ -6094,8 +6105,8 @@ namespace ts { isMethodSignature(node) ? updateMethodSignature(node, modifierArray, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) : isMethodDeclaration(node) ? updateMethodDeclaration(node, node.decorators, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) : isConstructorDeclaration(node) ? updateConstructorDeclaration(node, node.decorators, modifierArray, node.parameters, node.body) : - isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.type, node.body) : - isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.body) : + isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.type, node.questionToken, node.body) : + isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.questionToken, node.body) : isIndexSignatureDeclaration(node) ? updateIndexSignature(node, node.decorators, modifierArray, node.parameters, node.type) : isFunctionExpression(node) ? updateFunctionExpression(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) : isArrowFunction(node) ? updateArrowFunction(node, modifierArray, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body) : diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index c796e78d45190..b9314c4aa881e 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6747,13 +6747,14 @@ namespace ts { function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined, kind: AccessorDeclaration["kind"]): AccessorDeclaration { const name = parsePropertyName(); + const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); const typeParameters = parseTypeParameters(); const parameters = parseParameters(SignatureFlags.None); const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); const body = parseFunctionBlockOrSemicolon(SignatureFlags.None); const node = kind === SyntaxKind.GetAccessor - ? factory.createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body) - : factory.createSetAccessorDeclaration(decorators, modifiers, name, parameters, body); + ? factory.createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, questionToken, body) + : factory.createSetAccessorDeclaration(decorators, modifiers, name, parameters, questionToken, body); // Keep track of `typeParameters` (for both) and `type` (for setters) if they were parsed those indicate grammar errors node.typeParameters = typeParameters; if (type && node.kind === SyntaxKind.SetAccessor) (node as Mutable).type = type; diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index b17d861cc5155..19b2a1964dee1 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -950,6 +950,7 @@ namespace ts { input.name, updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)), ensureType(input, accessorType), + input.questionToken, /*body*/ undefined)); } case SyntaxKind.SetAccessor: { @@ -962,6 +963,7 @@ namespace ts { ensureModifiers(input), input.name, updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)), + input.questionToken, /*body*/ undefined)); } case SyntaxKind.PropertyDeclaration: diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 36a0f29d109e3..87ad987b2e615 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3649,10 +3649,10 @@ namespace ts { const parameters = visitParameterList(node.parameters, visitor, context); const body = transformFunctionBody(node); if (node.kind === SyntaxKind.GetAccessor) { - updated = factory.updateGetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, node.type, body); + updated = factory.updateGetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, node.type, node.questionToken, body); } else { - updated = factory.updateSetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, body); + updated = factory.updateSetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, node.questionToken, body); } exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None); convertedLoopState = savedConvertedLoopState; diff --git a/src/compiler/transformers/es2018.ts b/src/compiler/transformers/es2018.ts index e3923c79d9fc3..591cfb3efbe9b 100644 --- a/src/compiler/transformers/es2018.ts +++ b/src/compiler/transformers/es2018.ts @@ -864,6 +864,7 @@ namespace ts { visitNode(node.name, visitor, isPropertyName), visitParameterList(node.parameters, parameterVisitor, context), /*type*/ undefined, + visitNode>(/*questionToken*/ undefined, visitor, isToken), transformFunctionBody(node) ); enclosingFunctionFlags = savedEnclosingFunctionFlags; @@ -882,6 +883,7 @@ namespace ts { node.modifiers, visitNode(node.name, visitor, isPropertyName), visitParameterList(node.parameters, parameterVisitor, context), + visitNode>(/*questionToken*/ undefined, visitor, isToken), transformFunctionBody(node) ); enclosingFunctionFlags = savedEnclosingFunctionFlags; diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index f8cec499a8fd3..63f9546e1e632 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2070,6 +2070,7 @@ namespace ts { visitPropertyNameOfClassElement(node), visitParameterList(node.parameters, visitor, context), /*type*/ undefined, + /*questionToken*/ undefined, visitFunctionBody(node.body, visitor, context) || factory.createBlock([]) ); if (updated !== node) { @@ -2091,6 +2092,7 @@ namespace ts { visitNodes(node.modifiers, modifierVisitor, isModifier), visitPropertyNameOfClassElement(node), visitParameterList(node.parameters, visitor, context), + /*questionToken*/ undefined, visitFunctionBody(node.body, visitor, context) || factory.createBlock([]) ); if (updated !== node) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8a67511208893..55b1538f7846a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -7207,10 +7207,10 @@ namespace ts { updateMethodDeclaration(node: MethodDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; createConstructorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; updateConstructorDeclaration(node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - createGetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - updateGetAccessorDeclaration(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - createSetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - updateSetAccessorDeclaration(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; + createGetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, questionToken: QuestionToken | undefined, body: Block | undefined): GetAccessorDeclaration; + updateGetAccessorDeclaration(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, questionToken: QuestionToken | undefined, body: Block | undefined): GetAccessorDeclaration; + createSetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], questionToken: QuestionToken | undefined, body: Block | undefined): SetAccessorDeclaration; + updateSetAccessorDeclaration(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], questionToken: QuestionToken | undefined, body: Block | undefined): SetAccessorDeclaration; createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index ab7d0e6375ea5..f252603cc6cf1 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2628,6 +2628,8 @@ namespace ts { case SyntaxKind.PropertyAssignment: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: return (node as ParameterDeclaration | MethodDeclaration | PropertyDeclaration).questionToken !== undefined; } } diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index 6ea7025031751..693283851a91b 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -464,6 +464,7 @@ namespace ts { nodeVisitor(node.name, visitor, isPropertyName), visitParameterList(node.parameters, visitor, context, nodesVisitor), nodeVisitor(node.type, visitor, isTypeNode), + nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken), visitFunctionBody(node.body!, visitor, context, nodeVisitor)); case SyntaxKind.SetAccessor: @@ -473,6 +474,7 @@ namespace ts { nodesVisitor(node.modifiers, visitor, isModifier), nodeVisitor(node.name, visitor, isPropertyName), visitParameterList(node.parameters, visitor, context, nodesVisitor), + nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken), visitFunctionBody(node.body!, visitor, context, nodeVisitor)); case SyntaxKind.ClassStaticBlockDeclaration: diff --git a/src/services/codefixes/generateAccessors.ts b/src/services/codefixes/generateAccessors.ts index 1e02160fbfc1d..a7ce8399d2614 100644 --- a/src/services/codefixes/generateAccessors.ts +++ b/src/services/codefixes/generateAccessors.ts @@ -150,6 +150,7 @@ namespace ts.codefix { accessorName, /*parameters*/ undefined!, // TODO: GH#18217 type, + /*questionToken*/ undefined, factory.createBlock([ factory.createReturnStatement( createAccessorAccessExpression(fieldName, isStatic, container) @@ -171,6 +172,7 @@ namespace ts.codefix { /*questionToken*/ undefined, type )], + /*questionToken*/ undefined, factory.createBlock([ factory.createExpressionStatement( factory.createAssignment( diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 21981c8df5f40..f6b7bac0bf01e 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -116,6 +116,7 @@ namespace ts.codefix { name, emptyArray, typeNode, + /*questionToken*/ undefined, ambient ? undefined : body || createStubbedMethodBody(quotePreference))); } else { @@ -127,6 +128,7 @@ namespace ts.codefix { modifiers, name, createDummyParameters(1, [parameterName], [typeNode], 1, /*inJs*/ false), + /*questionToken*/ undefined, ambient ? undefined : body || createStubbedMethodBody(quotePreference))); } } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 55d0fe287b3a0..b33a2df63bb2e 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3369,10 +3369,10 @@ declare namespace ts { updateMethodDeclaration(node: MethodDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; createConstructorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; updateConstructorDeclaration(node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - createGetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - updateGetAccessorDeclaration(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - createSetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - updateSetAccessorDeclaration(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; + createGetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, questionToken: QuestionToken | undefined, body: Block | undefined): GetAccessorDeclaration; + updateGetAccessorDeclaration(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, questionToken: QuestionToken | undefined, body: Block | undefined): GetAccessorDeclaration; + createSetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], questionToken: QuestionToken | undefined, body: Block | undefined): SetAccessorDeclaration; + updateSetAccessorDeclaration(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], questionToken: QuestionToken | undefined, body: Block | undefined): SetAccessorDeclaration; createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; @@ -10713,13 +10713,13 @@ declare namespace ts { /** @deprecated Use `factory.updateConstructorDeclaration` or the factory supplied by your transformation context instead. */ const updateConstructor: (node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined) => ConstructorDeclaration; /** @deprecated Use `factory.createGetAccessorDeclaration` or the factory supplied by your transformation context instead. */ - const createGetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => GetAccessorDeclaration; + const createGetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, questionToken: QuestionToken | undefined, body: Block | undefined) => GetAccessorDeclaration; /** @deprecated Use `factory.updateGetAccessorDeclaration` or the factory supplied by your transformation context instead. */ - const updateGetAccessor: (node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => GetAccessorDeclaration; + const updateGetAccessor: (node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, questionToken: QuestionToken | undefined, body: Block | undefined) => GetAccessorDeclaration; /** @deprecated Use `factory.createSetAccessorDeclaration` or the factory supplied by your transformation context instead. */ - const createSetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined) => SetAccessorDeclaration; + const createSetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], questionToken: QuestionToken | undefined, body: Block | undefined) => SetAccessorDeclaration; /** @deprecated Use `factory.updateSetAccessorDeclaration` or the factory supplied by your transformation context instead. */ - const updateSetAccessor: (node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined) => SetAccessorDeclaration; + const updateSetAccessor: (node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], questionToken: QuestionToken | undefined, body: Block | undefined) => SetAccessorDeclaration; /** @deprecated Use `factory.createCallSignature` or the factory supplied by your transformation context instead. */ const createCallSignature: (typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) => CallSignatureDeclaration; /** @deprecated Use `factory.updateCallSignature` or the factory supplied by your transformation context instead. */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 0c17632055398..98e2c3216eb5f 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3369,10 +3369,10 @@ declare namespace ts { updateMethodDeclaration(node: MethodDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; createConstructorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; updateConstructorDeclaration(node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - createGetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - updateGetAccessorDeclaration(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - createSetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - updateSetAccessorDeclaration(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; + createGetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, questionToken: QuestionToken | undefined, body: Block | undefined): GetAccessorDeclaration; + updateGetAccessorDeclaration(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, questionToken: QuestionToken | undefined, body: Block | undefined): GetAccessorDeclaration; + createSetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], questionToken: QuestionToken | undefined, body: Block | undefined): SetAccessorDeclaration; + updateSetAccessorDeclaration(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], questionToken: QuestionToken | undefined, body: Block | undefined): SetAccessorDeclaration; createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; @@ -6902,13 +6902,13 @@ declare namespace ts { /** @deprecated Use `factory.updateConstructorDeclaration` or the factory supplied by your transformation context instead. */ const updateConstructor: (node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined) => ConstructorDeclaration; /** @deprecated Use `factory.createGetAccessorDeclaration` or the factory supplied by your transformation context instead. */ - const createGetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => GetAccessorDeclaration; + const createGetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, questionToken: QuestionToken | undefined, body: Block | undefined) => GetAccessorDeclaration; /** @deprecated Use `factory.updateGetAccessorDeclaration` or the factory supplied by your transformation context instead. */ - const updateGetAccessor: (node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => GetAccessorDeclaration; + const updateGetAccessor: (node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, questionToken: QuestionToken | undefined, body: Block | undefined) => GetAccessorDeclaration; /** @deprecated Use `factory.createSetAccessorDeclaration` or the factory supplied by your transformation context instead. */ - const createSetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined) => SetAccessorDeclaration; + const createSetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], questionToken: QuestionToken | undefined, body: Block | undefined) => SetAccessorDeclaration; /** @deprecated Use `factory.updateSetAccessorDeclaration` or the factory supplied by your transformation context instead. */ - const updateSetAccessor: (node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined) => SetAccessorDeclaration; + const updateSetAccessor: (node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], questionToken: QuestionToken | undefined, body: Block | undefined) => SetAccessorDeclaration; /** @deprecated Use `factory.createCallSignature` or the factory supplied by your transformation context instead. */ const createCallSignature: (typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) => CallSignatureDeclaration; /** @deprecated Use `factory.updateCallSignature` or the factory supplied by your transformation context instead. */ diff --git a/tests/baselines/reference/optionalAccessor1.errors.txt b/tests/baselines/reference/optionalAccessor1.errors.txt new file mode 100644 index 0000000000000..6acc3987a84ac --- /dev/null +++ b/tests/baselines/reference/optionalAccessor1.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/types/namedTypes/optionalAccessor1.ts(2,10): error TS1162: An object member cannot be declared optional. +tests/cases/conformance/types/namedTypes/optionalAccessor1.ts(3,10): error TS1162: An object member cannot be declared optional. + + +==== tests/cases/conformance/types/namedTypes/optionalAccessor1.ts (2 errors) ==== + const Foo = { + get x?() { return '' }, + ~ +!!! error TS1162: An object member cannot be declared optional. + set x?(value: string) {} + ~ +!!! error TS1162: An object member cannot be declared optional. + } + \ No newline at end of file diff --git a/tests/baselines/reference/optionalAccessor1.js b/tests/baselines/reference/optionalAccessor1.js new file mode 100644 index 0000000000000..721a932894803 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor1.js @@ -0,0 +1,12 @@ +//// [optionalAccessor1.ts] +const Foo = { + get x?() { return '' }, + set x?(value: string) {} +} + + +//// [optionalAccessor1.js] +const Foo = { + get x() { return ''; }, + set x(value) { } +}; diff --git a/tests/baselines/reference/optionalAccessor1.symbols b/tests/baselines/reference/optionalAccessor1.symbols new file mode 100644 index 0000000000000..e567b257e15f3 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor1.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor1.ts === +const Foo = { +>Foo : Symbol(Foo, Decl(optionalAccessor1.ts, 0, 5)) + + get x?() { return '' }, +>x : Symbol(x, Decl(optionalAccessor1.ts, 0, 13), Decl(optionalAccessor1.ts, 1, 27)) + + set x?(value: string) {} +>x : Symbol(x, Decl(optionalAccessor1.ts, 0, 13), Decl(optionalAccessor1.ts, 1, 27)) +>value : Symbol(value, Decl(optionalAccessor1.ts, 2, 11)) +} + diff --git a/tests/baselines/reference/optionalAccessor1.types b/tests/baselines/reference/optionalAccessor1.types new file mode 100644 index 0000000000000..884a6d09c8a15 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor1.types @@ -0,0 +1,14 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor1.ts === +const Foo = { +>Foo : { x?: string; } +>{ get x?() { return '' }, set x?(value: string) {}} : { x?: string; } + + get x?() { return '' }, +>x : string +>'' : "" + + set x?(value: string) {} +>x : string +>value : string +} + diff --git a/tests/baselines/reference/optionalAccessor2.js b/tests/baselines/reference/optionalAccessor2.js new file mode 100644 index 0000000000000..c36f9b36d7831 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor2.js @@ -0,0 +1,15 @@ +//// [optionalAccessor2.ts] +class C { + get x?() { return '' } + set x?(value: string) {} +} + +const foo: C = { }; + + +//// [optionalAccessor2.js] +class C { + get x() { return ''; } + set x(value) { } +} +const foo = {}; diff --git a/tests/baselines/reference/optionalAccessor2.symbols b/tests/baselines/reference/optionalAccessor2.symbols new file mode 100644 index 0000000000000..773058983328b --- /dev/null +++ b/tests/baselines/reference/optionalAccessor2.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor2.ts === +class C { +>C : Symbol(C, Decl(optionalAccessor2.ts, 0, 0)) + + get x?() { return '' } +>x : Symbol(C.x, Decl(optionalAccessor2.ts, 0, 9), Decl(optionalAccessor2.ts, 1, 26)) + + set x?(value: string) {} +>x : Symbol(C.x, Decl(optionalAccessor2.ts, 0, 9), Decl(optionalAccessor2.ts, 1, 26)) +>value : Symbol(value, Decl(optionalAccessor2.ts, 2, 11)) +} + +const foo: C = { }; +>foo : Symbol(foo, Decl(optionalAccessor2.ts, 5, 5)) +>C : Symbol(C, Decl(optionalAccessor2.ts, 0, 0)) + diff --git a/tests/baselines/reference/optionalAccessor2.types b/tests/baselines/reference/optionalAccessor2.types new file mode 100644 index 0000000000000..5aacfdcabf64f --- /dev/null +++ b/tests/baselines/reference/optionalAccessor2.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor2.ts === +class C { +>C : C + + get x?() { return '' } +>x : string +>'' : "" + + set x?(value: string) {} +>x : string +>value : string +} + +const foo: C = { }; +>foo : C +>{ } : {} + diff --git a/tests/baselines/reference/optionalAccessor3.js b/tests/baselines/reference/optionalAccessor3.js new file mode 100644 index 0000000000000..b996e4369051c --- /dev/null +++ b/tests/baselines/reference/optionalAccessor3.js @@ -0,0 +1,12 @@ +//// [optionalAccessor3.ts] +interface I { + get x?(): string; + set x?(value: string); +} + +class C implements I {} + + +//// [optionalAccessor3.js] +class C { +} diff --git a/tests/baselines/reference/optionalAccessor3.symbols b/tests/baselines/reference/optionalAccessor3.symbols new file mode 100644 index 0000000000000..2a1f3f65366c2 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor3.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor3.ts === +interface I { +>I : Symbol(I, Decl(optionalAccessor3.ts, 0, 0)) + + get x?(): string; +>x : Symbol(I.x, Decl(optionalAccessor3.ts, 0, 13), Decl(optionalAccessor3.ts, 1, 21)) + + set x?(value: string); +>x : Symbol(I.x, Decl(optionalAccessor3.ts, 0, 13), Decl(optionalAccessor3.ts, 1, 21)) +>value : Symbol(value, Decl(optionalAccessor3.ts, 2, 11)) +} + +class C implements I {} +>C : Symbol(C, Decl(optionalAccessor3.ts, 3, 1)) +>I : Symbol(I, Decl(optionalAccessor3.ts, 0, 0)) + diff --git a/tests/baselines/reference/optionalAccessor3.types b/tests/baselines/reference/optionalAccessor3.types new file mode 100644 index 0000000000000..eec63ea1a9fa4 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor3.types @@ -0,0 +1,13 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor3.ts === +interface I { + get x?(): string; +>x : string + + set x?(value: string); +>x : string +>value : string +} + +class C implements I {} +>C : C + diff --git a/tests/baselines/reference/optionalAccessor4.js b/tests/baselines/reference/optionalAccessor4.js new file mode 100644 index 0000000000000..5aaabeb5b0556 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor4.js @@ -0,0 +1,16 @@ +//// [optionalAccessor4.ts] +class C { + get x?() { return '' } + set x?(value: string) {} +} + +const foo: C = { }; + + +//// [optionalAccessor4.js] +"use strict"; +class C { + get x() { return ''; } + set x(value) { } +} +const foo = {}; diff --git a/tests/baselines/reference/optionalAccessor4.symbols b/tests/baselines/reference/optionalAccessor4.symbols new file mode 100644 index 0000000000000..2cb53fadca18f --- /dev/null +++ b/tests/baselines/reference/optionalAccessor4.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor4.ts === +class C { +>C : Symbol(C, Decl(optionalAccessor4.ts, 0, 0)) + + get x?() { return '' } +>x : Symbol(C.x, Decl(optionalAccessor4.ts, 0, 9), Decl(optionalAccessor4.ts, 1, 26)) + + set x?(value: string) {} +>x : Symbol(C.x, Decl(optionalAccessor4.ts, 0, 9), Decl(optionalAccessor4.ts, 1, 26)) +>value : Symbol(value, Decl(optionalAccessor4.ts, 2, 11)) +} + +const foo: C = { }; +>foo : Symbol(foo, Decl(optionalAccessor4.ts, 5, 5)) +>C : Symbol(C, Decl(optionalAccessor4.ts, 0, 0)) + diff --git a/tests/baselines/reference/optionalAccessor4.types b/tests/baselines/reference/optionalAccessor4.types new file mode 100644 index 0000000000000..c4ca7b4d2236c --- /dev/null +++ b/tests/baselines/reference/optionalAccessor4.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor4.ts === +class C { +>C : C + + get x?() { return '' } +>x : string | undefined +>'' : "" + + set x?(value: string) {} +>x : string | undefined +>value : string +} + +const foo: C = { }; +>foo : C +>{ } : {} + diff --git a/tests/baselines/reference/optionalAccessor5.js b/tests/baselines/reference/optionalAccessor5.js new file mode 100644 index 0000000000000..e22809020d0c6 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor5.js @@ -0,0 +1,10 @@ +//// [optionalAccessor5.ts] +class C { + get x?(): string; +} + + +//// [optionalAccessor5.js] +class C { + get x() { } +} diff --git a/tests/baselines/reference/optionalAccessor5.symbols b/tests/baselines/reference/optionalAccessor5.symbols new file mode 100644 index 0000000000000..f5bb85072de64 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor5.symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor5.ts === +class C { +>C : Symbol(C, Decl(optionalAccessor5.ts, 0, 0)) + + get x?(): string; +>x : Symbol(C.x, Decl(optionalAccessor5.ts, 0, 9)) +} + diff --git a/tests/baselines/reference/optionalAccessor5.types b/tests/baselines/reference/optionalAccessor5.types new file mode 100644 index 0000000000000..08f299298ccee --- /dev/null +++ b/tests/baselines/reference/optionalAccessor5.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor5.ts === +class C { +>C : C + + get x?(): string; +>x : string +} + diff --git a/tests/baselines/reference/optionalAccessor6.js b/tests/baselines/reference/optionalAccessor6.js new file mode 100644 index 0000000000000..423dd7eafc6a2 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor6.js @@ -0,0 +1,19 @@ +//// [optionalAccessor6.ts] +class C { + get x?() { return '' } + set x?(value: string) {} +} + + +//// [optionalAccessor6.js] +class C { + get x() { return ''; } + set x(value) { } +} + + +//// [optionalAccessor6.d.ts] +declare class C { + get x?(): string; + set x?(value: string); +} diff --git a/tests/baselines/reference/optionalAccessor6.symbols b/tests/baselines/reference/optionalAccessor6.symbols new file mode 100644 index 0000000000000..060479eb0aeb4 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor6.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor6.ts === +class C { +>C : Symbol(C, Decl(optionalAccessor6.ts, 0, 0)) + + get x?() { return '' } +>x : Symbol(C.x, Decl(optionalAccessor6.ts, 0, 9), Decl(optionalAccessor6.ts, 1, 26)) + + set x?(value: string) {} +>x : Symbol(C.x, Decl(optionalAccessor6.ts, 0, 9), Decl(optionalAccessor6.ts, 1, 26)) +>value : Symbol(value, Decl(optionalAccessor6.ts, 2, 11)) +} + diff --git a/tests/baselines/reference/optionalAccessor6.types b/tests/baselines/reference/optionalAccessor6.types new file mode 100644 index 0000000000000..27051f4ec0db7 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor6.types @@ -0,0 +1,13 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor6.ts === +class C { +>C : C + + get x?() { return '' } +>x : string +>'' : "" + + set x?(value: string) {} +>x : string +>value : string +} + diff --git a/tests/baselines/reference/optionalAccessor7.js b/tests/baselines/reference/optionalAccessor7.js new file mode 100644 index 0000000000000..fd52efc6ecf77 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor7.js @@ -0,0 +1,21 @@ +//// [optionalAccessor7.ts] +class A { + get x?() { return '' } + set x?(value: string) {} +} + +class B extends A { + get x() { return '' } + set x(value: string) { } +} + + +//// [optionalAccessor7.js] +class A { + get x() { return ''; } + set x(value) { } +} +class B extends A { + get x() { return ''; } + set x(value) { } +} diff --git a/tests/baselines/reference/optionalAccessor7.symbols b/tests/baselines/reference/optionalAccessor7.symbols new file mode 100644 index 0000000000000..02a11aa89be1c --- /dev/null +++ b/tests/baselines/reference/optionalAccessor7.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor7.ts === +class A { +>A : Symbol(A, Decl(optionalAccessor7.ts, 0, 0)) + + get x?() { return '' } +>x : Symbol(A.x, Decl(optionalAccessor7.ts, 0, 9), Decl(optionalAccessor7.ts, 1, 26)) + + set x?(value: string) {} +>x : Symbol(A.x, Decl(optionalAccessor7.ts, 0, 9), Decl(optionalAccessor7.ts, 1, 26)) +>value : Symbol(value, Decl(optionalAccessor7.ts, 2, 11)) +} + +class B extends A { +>B : Symbol(B, Decl(optionalAccessor7.ts, 3, 1)) +>A : Symbol(A, Decl(optionalAccessor7.ts, 0, 0)) + + get x() { return '' } +>x : Symbol(B.x, Decl(optionalAccessor7.ts, 5, 19), Decl(optionalAccessor7.ts, 6, 25)) + + set x(value: string) { } +>x : Symbol(B.x, Decl(optionalAccessor7.ts, 5, 19), Decl(optionalAccessor7.ts, 6, 25)) +>value : Symbol(value, Decl(optionalAccessor7.ts, 7, 10)) +} + diff --git a/tests/baselines/reference/optionalAccessor7.types b/tests/baselines/reference/optionalAccessor7.types new file mode 100644 index 0000000000000..3902fd57ddd0a --- /dev/null +++ b/tests/baselines/reference/optionalAccessor7.types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor7.ts === +class A { +>A : A + + get x?() { return '' } +>x : string +>'' : "" + + set x?(value: string) {} +>x : string +>value : string +} + +class B extends A { +>B : B +>A : A + + get x() { return '' } +>x : string +>'' : "" + + set x(value: string) { } +>x : string +>value : string +} + diff --git a/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).js b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).js new file mode 100644 index 0000000000000..649c45f439ea3 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).js @@ -0,0 +1,19 @@ +//// [optionalAccessor8.ts] +export class C { + get foo?(): number { return 1; } + set foo?(value: number) {} +} + +declare let x: { + foo: number | undefined; +} + +let y: C = x; + + +//// [optionalAccessor8.js] +export class C { + get foo() { return 1; } + set foo(value) { } +} +let y = x; diff --git a/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).symbols b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).symbols new file mode 100644 index 0000000000000..370f5859dfdc2 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor8.ts === +export class C { +>C : Symbol(C, Decl(optionalAccessor8.ts, 0, 0)) + + get foo?(): number { return 1; } +>foo : Symbol(C.foo, Decl(optionalAccessor8.ts, 0, 16), Decl(optionalAccessor8.ts, 1, 36)) + + set foo?(value: number) {} +>foo : Symbol(C.foo, Decl(optionalAccessor8.ts, 0, 16), Decl(optionalAccessor8.ts, 1, 36)) +>value : Symbol(value, Decl(optionalAccessor8.ts, 2, 13)) +} + +declare let x: { +>x : Symbol(x, Decl(optionalAccessor8.ts, 5, 11)) + + foo: number | undefined; +>foo : Symbol(foo, Decl(optionalAccessor8.ts, 5, 16)) +} + +let y: C = x; +>y : Symbol(y, Decl(optionalAccessor8.ts, 9, 3)) +>C : Symbol(C, Decl(optionalAccessor8.ts, 0, 0)) +>x : Symbol(x, Decl(optionalAccessor8.ts, 5, 11)) + diff --git a/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).types b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).types new file mode 100644 index 0000000000000..3d37bd4207815 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=false).types @@ -0,0 +1,24 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor8.ts === +export class C { +>C : C + + get foo?(): number { return 1; } +>foo : number | undefined +>1 : 1 + + set foo?(value: number) {} +>foo : number | undefined +>value : number +} + +declare let x: { +>x : { foo: number | undefined; } + + foo: number | undefined; +>foo : number | undefined +} + +let y: C = x; +>y : C +>x : { foo: number | undefined; } + diff --git a/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).errors.txt b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).errors.txt new file mode 100644 index 0000000000000..80f795ec577dd --- /dev/null +++ b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).errors.txt @@ -0,0 +1,23 @@ +tests/cases/conformance/types/namedTypes/optionalAccessor8.ts(10,5): error TS2375: Type '{ foo: number | undefined; }' is not assignable to type 'C' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties. + Types of property 'foo' are incompatible. + Type 'number | undefined' is not assignable to type 'number'. + Type 'undefined' is not assignable to type 'number'. + + +==== tests/cases/conformance/types/namedTypes/optionalAccessor8.ts (1 errors) ==== + export class C { + get foo?(): number { return 1; } + set foo?(value: number) {} + } + + declare let x: { + foo: number | undefined; + } + + let y: C = x; + ~ +!!! error TS2375: Type '{ foo: number | undefined; }' is not assignable to type 'C' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties. +!!! error TS2375: Types of property 'foo' are incompatible. +!!! error TS2375: Type 'number | undefined' is not assignable to type 'number'. +!!! error TS2375: Type 'undefined' is not assignable to type 'number'. + \ No newline at end of file diff --git a/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).js b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).js new file mode 100644 index 0000000000000..649c45f439ea3 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).js @@ -0,0 +1,19 @@ +//// [optionalAccessor8.ts] +export class C { + get foo?(): number { return 1; } + set foo?(value: number) {} +} + +declare let x: { + foo: number | undefined; +} + +let y: C = x; + + +//// [optionalAccessor8.js] +export class C { + get foo() { return 1; } + set foo(value) { } +} +let y = x; diff --git a/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).symbols b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).symbols new file mode 100644 index 0000000000000..370f5859dfdc2 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor8.ts === +export class C { +>C : Symbol(C, Decl(optionalAccessor8.ts, 0, 0)) + + get foo?(): number { return 1; } +>foo : Symbol(C.foo, Decl(optionalAccessor8.ts, 0, 16), Decl(optionalAccessor8.ts, 1, 36)) + + set foo?(value: number) {} +>foo : Symbol(C.foo, Decl(optionalAccessor8.ts, 0, 16), Decl(optionalAccessor8.ts, 1, 36)) +>value : Symbol(value, Decl(optionalAccessor8.ts, 2, 13)) +} + +declare let x: { +>x : Symbol(x, Decl(optionalAccessor8.ts, 5, 11)) + + foo: number | undefined; +>foo : Symbol(foo, Decl(optionalAccessor8.ts, 5, 16)) +} + +let y: C = x; +>y : Symbol(y, Decl(optionalAccessor8.ts, 9, 3)) +>C : Symbol(C, Decl(optionalAccessor8.ts, 0, 0)) +>x : Symbol(x, Decl(optionalAccessor8.ts, 5, 11)) + diff --git a/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).types b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).types new file mode 100644 index 0000000000000..3d37bd4207815 --- /dev/null +++ b/tests/baselines/reference/optionalAccessor8(exactoptionalpropertytypes=true).types @@ -0,0 +1,24 @@ +=== tests/cases/conformance/types/namedTypes/optionalAccessor8.ts === +export class C { +>C : C + + get foo?(): number { return 1; } +>foo : number | undefined +>1 : 1 + + set foo?(value: number) {} +>foo : number | undefined +>value : number +} + +declare let x: { +>x : { foo: number | undefined; } + + foo: number | undefined; +>foo : number | undefined +} + +let y: C = x; +>y : C +>x : { foo: number | undefined; } + diff --git a/tests/cases/conformance/types/namedTypes/optionalAccessor1.ts b/tests/cases/conformance/types/namedTypes/optionalAccessor1.ts new file mode 100644 index 0000000000000..2c288ce9a5e72 --- /dev/null +++ b/tests/cases/conformance/types/namedTypes/optionalAccessor1.ts @@ -0,0 +1,6 @@ +// @target: es2015 + +const Foo = { + get x?() { return '' }, + set x?(value: string) {} +} diff --git a/tests/cases/conformance/types/namedTypes/optionalAccessor2.ts b/tests/cases/conformance/types/namedTypes/optionalAccessor2.ts new file mode 100644 index 0000000000000..24f192f8dab5d --- /dev/null +++ b/tests/cases/conformance/types/namedTypes/optionalAccessor2.ts @@ -0,0 +1,8 @@ +// @target: es2015 + +class C { + get x?() { return '' } + set x?(value: string) {} +} + +const foo: C = { }; diff --git a/tests/cases/conformance/types/namedTypes/optionalAccessor3.ts b/tests/cases/conformance/types/namedTypes/optionalAccessor3.ts new file mode 100644 index 0000000000000..5e797e1b15382 --- /dev/null +++ b/tests/cases/conformance/types/namedTypes/optionalAccessor3.ts @@ -0,0 +1,8 @@ +// @target: es2015 + +interface I { + get x?(): string; + set x?(value: string); +} + +class C implements I {} diff --git a/tests/cases/conformance/types/namedTypes/optionalAccessor4.ts b/tests/cases/conformance/types/namedTypes/optionalAccessor4.ts new file mode 100644 index 0000000000000..8e8b336016d15 --- /dev/null +++ b/tests/cases/conformance/types/namedTypes/optionalAccessor4.ts @@ -0,0 +1,9 @@ +// @target: es2015 +// @strict: true + +class C { + get x?() { return '' } + set x?(value: string) {} +} + +const foo: C = { }; diff --git a/tests/cases/conformance/types/namedTypes/optionalAccessor5.ts b/tests/cases/conformance/types/namedTypes/optionalAccessor5.ts new file mode 100644 index 0000000000000..cf3de064be6bc --- /dev/null +++ b/tests/cases/conformance/types/namedTypes/optionalAccessor5.ts @@ -0,0 +1,5 @@ +// @target: es2015 + +class C { + get x?(): string; +} diff --git a/tests/cases/conformance/types/namedTypes/optionalAccessor6.ts b/tests/cases/conformance/types/namedTypes/optionalAccessor6.ts new file mode 100644 index 0000000000000..d5849e4a9def9 --- /dev/null +++ b/tests/cases/conformance/types/namedTypes/optionalAccessor6.ts @@ -0,0 +1,7 @@ +// @target: es2015 +// @declaration: true + +class C { + get x?() { return '' } + set x?(value: string) {} +} diff --git a/tests/cases/conformance/types/namedTypes/optionalAccessor7.ts b/tests/cases/conformance/types/namedTypes/optionalAccessor7.ts new file mode 100644 index 0000000000000..392c7b066ce99 --- /dev/null +++ b/tests/cases/conformance/types/namedTypes/optionalAccessor7.ts @@ -0,0 +1,11 @@ +// @target: es2015 + +class A { + get x?() { return '' } + set x?(value: string) {} +} + +class B extends A { + get x() { return '' } + set x(value: string) { } +} diff --git a/tests/cases/conformance/types/namedTypes/optionalAccessor8.ts b/tests/cases/conformance/types/namedTypes/optionalAccessor8.ts new file mode 100644 index 0000000000000..a6c4966c10b4a --- /dev/null +++ b/tests/cases/conformance/types/namedTypes/optionalAccessor8.ts @@ -0,0 +1,14 @@ +// @target: es2015 +// @strict: true +// @exactOptionalPropertyTypes: true, false + +export class C { + get foo?(): number { return 1; } + set foo?(value: number) {} +} + +declare let x: { + foo: number | undefined; +} + +let y: C = x;