mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-24 11:43:18 -05:00
Merge pull request #8625 from Microsoft/optionalClassProperties
Optional class properties
This commit is contained in:
@@ -79,6 +79,7 @@ namespace ts {
|
||||
getIndexTypeOfType,
|
||||
getBaseTypes,
|
||||
getReturnTypeOfSignature,
|
||||
getNonNullableType,
|
||||
getSymbolsInScope,
|
||||
getSymbolAtLocation,
|
||||
getShorthandAssignmentValueSymbol,
|
||||
@@ -2884,6 +2885,10 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function addOptionality(type: Type, optional: boolean): Type {
|
||||
return strictNullChecks && optional ? addNullableKind(type, TypeFlags.Undefined) : type;
|
||||
}
|
||||
|
||||
// Return the inferred type for a variable, parameter, or property declaration
|
||||
function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration): Type {
|
||||
if (declaration.flags & NodeFlags.JavaScriptFile) {
|
||||
@@ -2915,8 +2920,7 @@ namespace ts {
|
||||
|
||||
// Use type from type annotation if one is present
|
||||
if (declaration.type) {
|
||||
const type = getTypeFromTypeNode(declaration.type);
|
||||
return strictNullChecks && declaration.questionToken ? addNullableKind(type, TypeFlags.Undefined) : type;
|
||||
return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ !!declaration.questionToken);
|
||||
}
|
||||
|
||||
if (declaration.kind === SyntaxKind.Parameter) {
|
||||
@@ -2938,13 +2942,13 @@ namespace ts {
|
||||
? getContextuallyTypedThisType(func)
|
||||
: getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
|
||||
if (type) {
|
||||
return strictNullChecks && declaration.questionToken ? addNullableKind(type, TypeFlags.Undefined) : type;
|
||||
return addOptionality(type, /*optional*/ !!declaration.questionToken);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the type of the initializer expression if one is present
|
||||
if (declaration.initializer) {
|
||||
return checkExpressionCached(declaration.initializer);
|
||||
return addOptionality(checkExpressionCached(declaration.initializer), /*optional*/ !!declaration.questionToken);
|
||||
}
|
||||
|
||||
// If it is a short-hand property assignment, use the type of the identifier
|
||||
@@ -3215,7 +3219,9 @@ namespace ts {
|
||||
function getTypeOfFuncClassEnumModule(symbol: Symbol): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.type) {
|
||||
links.type = createObjectType(TypeFlags.Anonymous, symbol);
|
||||
const type = createObjectType(TypeFlags.Anonymous, symbol);
|
||||
links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ?
|
||||
addNullableKind(type, TypeFlags.Undefined) : type;
|
||||
}
|
||||
return links.type;
|
||||
}
|
||||
@@ -7614,11 +7620,12 @@ namespace ts {
|
||||
getInitialTypeOfBindingElement(<BindingElement>node);
|
||||
}
|
||||
|
||||
function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType: Type) {
|
||||
function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean) {
|
||||
let key: string;
|
||||
if (!reference.flowNode || declaredType === initialType && !(declaredType.flags & TypeFlags.Narrowable)) {
|
||||
if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
|
||||
return declaredType;
|
||||
}
|
||||
const initialType = assumeInitialized ? declaredType : addNullableKind(declaredType, TypeFlags.Undefined);
|
||||
const visitedFlowStart = visitedFlowCount;
|
||||
const result = getTypeAtFlowNode(reference.flowNode);
|
||||
visitedFlowCount = visitedFlowStart;
|
||||
@@ -8092,11 +8099,11 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
const declaration = localOrExportSymbol.valueDeclaration;
|
||||
const defaultsToDeclaredType = !strictNullChecks || type.flags & TypeFlags.Any || !declaration ||
|
||||
const assumeInitialized = !strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || !declaration ||
|
||||
getRootDeclaration(declaration).kind === SyntaxKind.Parameter || isInAmbientContext(declaration) ||
|
||||
getContainingFunctionOrModule(declaration) !== getContainingFunctionOrModule(node);
|
||||
const flowType = getFlowTypeOfReference(node, type, defaultsToDeclaredType ? type : addNullableKind(type, TypeFlags.Undefined));
|
||||
if (strictNullChecks && !(type.flags & TypeFlags.Any) && !(getNullableKind(type) & TypeFlags.Undefined) && getNullableKind(flowType) & TypeFlags.Undefined) {
|
||||
const flowType = getFlowTypeOfReference(node, type, assumeInitialized);
|
||||
if (!assumeInitialized && !(getNullableKind(type) & TypeFlags.Undefined) && getNullableKind(flowType) & TypeFlags.Undefined) {
|
||||
error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
|
||||
// Return the declared type to reduce follow-on errors
|
||||
return type;
|
||||
@@ -8344,7 +8351,7 @@ namespace ts {
|
||||
if (isClassLike(container.parent)) {
|
||||
const symbol = getSymbolOfNode(container.parent);
|
||||
const type = container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (<InterfaceType>getDeclaredTypeOfSymbol(symbol)).thisType;
|
||||
return getFlowTypeOfReference(node, type, type);
|
||||
return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true);
|
||||
}
|
||||
|
||||
if (isInJavaScriptFile(node)) {
|
||||
@@ -9919,7 +9926,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
const propType = getTypeOfSymbol(prop);
|
||||
if (node.kind !== SyntaxKind.PropertyAccessExpression || !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) || isAssignmentTarget(node)) {
|
||||
if (node.kind !== SyntaxKind.PropertyAccessExpression || isAssignmentTarget(node) ||
|
||||
!(propType.flags & TypeFlags.Union) && !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor))) {
|
||||
return propType;
|
||||
}
|
||||
const leftmostNode = getLeftmostIdentifierOrThis(node);
|
||||
@@ -9936,7 +9944,7 @@ namespace ts {
|
||||
return propType;
|
||||
}
|
||||
}
|
||||
return getFlowTypeOfReference(node, propType, propType);
|
||||
return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true);
|
||||
}
|
||||
|
||||
function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {
|
||||
@@ -13400,7 +13408,7 @@ namespace ts {
|
||||
|
||||
// Abstract methods can't have an implementation -- in particular, they don't need one.
|
||||
if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
|
||||
!(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract)) {
|
||||
!(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) {
|
||||
reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
|
||||
}
|
||||
|
||||
@@ -18290,7 +18298,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional)) {
|
||||
if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional)) {
|
||||
return true;
|
||||
}
|
||||
else if (node.body === undefined) {
|
||||
@@ -18299,9 +18307,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (isClassLike(node.parent)) {
|
||||
if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional)) {
|
||||
return true;
|
||||
}
|
||||
// Technically, computed properties in ambient contexts is disallowed
|
||||
// for property declarations and accessors too, not just methods.
|
||||
// However, property declarations disallow computed names in general,
|
||||
@@ -18523,8 +18528,7 @@ namespace ts {
|
||||
|
||||
function checkGrammarProperty(node: PropertyDeclaration) {
|
||||
if (isClassLike(node.parent)) {
|
||||
if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional) ||
|
||||
checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol)) {
|
||||
if (checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1129,7 +1129,7 @@ namespace ts {
|
||||
// what we want, namely the name expression enclosed in brackets.
|
||||
writeTextOfNode(currentText, node.name);
|
||||
// If optional property emit ?
|
||||
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && hasQuestionToken(node)) {
|
||||
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.Parameter) && hasQuestionToken(node)) {
|
||||
write("?");
|
||||
}
|
||||
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) {
|
||||
|
||||
@@ -315,10 +315,6 @@
|
||||
"category": "Error",
|
||||
"code": 1110
|
||||
},
|
||||
"A class member cannot be declared optional.": {
|
||||
"category": "Error",
|
||||
"code": 1112
|
||||
},
|
||||
"A 'default' clause cannot appear more than once in a 'switch' statement.": {
|
||||
"category": "Error",
|
||||
"code": 1113
|
||||
|
||||
@@ -1772,6 +1772,7 @@ namespace ts {
|
||||
getIndexTypeOfType(type: Type, kind: IndexKind): Type;
|
||||
getBaseTypes(type: InterfaceType): ObjectType[];
|
||||
getReturnTypeOfSignature(signature: Signature): Type;
|
||||
getNonNullableType(type: Type): Type;
|
||||
|
||||
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
|
||||
getSymbolAtLocation(node: Node): Symbol;
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace ts {
|
||||
getStringIndexType(): Type;
|
||||
getNumberIndexType(): Type;
|
||||
getBaseTypes(): ObjectType[];
|
||||
getNonNullableType(): Type;
|
||||
}
|
||||
|
||||
export interface Signature {
|
||||
@@ -735,6 +736,9 @@ namespace ts {
|
||||
? this.checker.getBaseTypes(<InterfaceType><Type>this)
|
||||
: undefined;
|
||||
}
|
||||
getNonNullableType(): Type {
|
||||
return this.checker.getNonNullableType(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SignatureObject implements Signature {
|
||||
@@ -4366,7 +4370,7 @@ namespace ts {
|
||||
(location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration
|
||||
// get the signature from the declaration and write it
|
||||
const functionDeclaration = <FunctionLikeDeclaration>location.parent;
|
||||
const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures();
|
||||
const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures();
|
||||
if (!typeChecker.isImplementationOfOverload(functionDeclaration)) {
|
||||
signature = typeChecker.getSignatureFromDeclaration(functionDeclaration);
|
||||
}
|
||||
@@ -4564,7 +4568,7 @@ namespace ts {
|
||||
symbolFlags & SymbolFlags.Signature ||
|
||||
symbolFlags & SymbolFlags.Accessor ||
|
||||
symbolKind === ScriptElementKind.memberFunctionElement) {
|
||||
const allSignatures = type.getCallSignatures();
|
||||
const allSignatures = type.getNonNullableType().getCallSignatures();
|
||||
addSignatureDisplayParts(allSignatures[0], allSignatures);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts(4,6): error TS1112: A class member cannot be declared optional.
|
||||
tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts(5,6): error TS1112: A class member cannot be declared optional.
|
||||
tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts(9,6): error TS1112: A class member cannot be declared optional.
|
||||
tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts(10,6): error TS1112: A class member cannot be declared optional.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts (4 errors) ====
|
||||
// classes do not permit optional parameters, these are errors
|
||||
|
||||
class C {
|
||||
x?: string;
|
||||
~
|
||||
!!! error TS1112: A class member cannot be declared optional.
|
||||
f?() {}
|
||||
~
|
||||
!!! error TS1112: A class member cannot be declared optional.
|
||||
}
|
||||
|
||||
class C2<T> {
|
||||
x?: T;
|
||||
~
|
||||
!!! error TS1112: A class member cannot be declared optional.
|
||||
f?(x: T) {}
|
||||
~
|
||||
!!! error TS1112: A class member cannot be declared optional.
|
||||
}
|
||||
26
tests/baselines/reference/classWithOptionalParameter.symbols
Normal file
26
tests/baselines/reference/classWithOptionalParameter.symbols
Normal file
@@ -0,0 +1,26 @@
|
||||
=== tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts ===
|
||||
// classes do not permit optional parameters, these are errors
|
||||
|
||||
class C {
|
||||
>C : Symbol(C, Decl(classWithOptionalParameter.ts, 0, 0))
|
||||
|
||||
x?: string;
|
||||
>x : Symbol(C.x, Decl(classWithOptionalParameter.ts, 2, 9))
|
||||
|
||||
f?() {}
|
||||
>f : Symbol(C.f, Decl(classWithOptionalParameter.ts, 3, 15))
|
||||
}
|
||||
|
||||
class C2<T> {
|
||||
>C2 : Symbol(C2, Decl(classWithOptionalParameter.ts, 5, 1))
|
||||
>T : Symbol(T, Decl(classWithOptionalParameter.ts, 7, 9))
|
||||
|
||||
x?: T;
|
||||
>x : Symbol(C2.x, Decl(classWithOptionalParameter.ts, 7, 13))
|
||||
>T : Symbol(T, Decl(classWithOptionalParameter.ts, 7, 9))
|
||||
|
||||
f?(x: T) {}
|
||||
>f : Symbol(C2.f, Decl(classWithOptionalParameter.ts, 8, 10))
|
||||
>x : Symbol(x, Decl(classWithOptionalParameter.ts, 9, 7))
|
||||
>T : Symbol(T, Decl(classWithOptionalParameter.ts, 7, 9))
|
||||
}
|
||||
26
tests/baselines/reference/classWithOptionalParameter.types
Normal file
26
tests/baselines/reference/classWithOptionalParameter.types
Normal file
@@ -0,0 +1,26 @@
|
||||
=== tests/cases/conformance/types/namedTypes/classWithOptionalParameter.ts ===
|
||||
// classes do not permit optional parameters, these are errors
|
||||
|
||||
class C {
|
||||
>C : C
|
||||
|
||||
x?: string;
|
||||
>x : string
|
||||
|
||||
f?() {}
|
||||
>f : () => void
|
||||
}
|
||||
|
||||
class C2<T> {
|
||||
>C2 : C2<T>
|
||||
>T : T
|
||||
|
||||
x?: T;
|
||||
>x : T
|
||||
>T : T
|
||||
|
||||
f?(x: T) {}
|
||||
>f : (x: T) => void
|
||||
>x : T
|
||||
>T : T
|
||||
}
|
||||
@@ -247,7 +247,7 @@ export declare class ConstructorWithPrivateParameterProperty {
|
||||
constructor(x: string);
|
||||
}
|
||||
export declare class ConstructorWithOptionalParameterProperty {
|
||||
x: string;
|
||||
x?: string;
|
||||
constructor(x?: string);
|
||||
}
|
||||
export declare class ConstructorWithParameterInitializer {
|
||||
@@ -281,7 +281,7 @@ declare class GlobalConstructorWithPrivateParameterProperty {
|
||||
constructor(x: string);
|
||||
}
|
||||
declare class GlobalConstructorWithOptionalParameterProperty {
|
||||
x: string;
|
||||
x?: string;
|
||||
constructor(x?: string);
|
||||
}
|
||||
declare class GlobalConstructorWithParameterInitializer {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
tests/cases/compiler/objectLiteralMemberWithQuestionMark1.ts(1,14): error TS1112: A class member cannot be declared optional.
|
||||
tests/cases/compiler/objectLiteralMemberWithQuestionMark1.ts(1,14): error TS1162: An object member cannot be declared optional.
|
||||
|
||||
|
||||
==== tests/cases/compiler/objectLiteralMemberWithQuestionMark1.ts (1 errors) ====
|
||||
var v = { foo?() { } }
|
||||
~
|
||||
!!! error TS1112: A class member cannot be declared optional.
|
||||
!!! error TS1162: An object member cannot be declared optional.
|
||||
@@ -1,9 +1,7 @@
|
||||
tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts(12,6): error TS1112: A class member cannot be declared optional.
|
||||
tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts(20,6): error TS1112: A class member cannot be declared optional.
|
||||
tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts(24,6): error TS1162: An object member cannot be declared optional.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts (3 errors) ====
|
||||
==== tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts (1 errors) ====
|
||||
// Basic uses of optional properties
|
||||
|
||||
var a: {
|
||||
@@ -15,9 +13,7 @@ tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWith
|
||||
}
|
||||
|
||||
class C {
|
||||
x?: number; // error
|
||||
~
|
||||
!!! error TS1112: A class member cannot be declared optional.
|
||||
x?: number; // ok
|
||||
}
|
||||
|
||||
interface I2<T> {
|
||||
@@ -25,9 +21,7 @@ tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWith
|
||||
}
|
||||
|
||||
class C2<T> {
|
||||
x?: T; // error
|
||||
~
|
||||
!!! error TS1112: A class member cannot be declared optional.
|
||||
x?: T; // ok
|
||||
}
|
||||
|
||||
var b = {
|
||||
|
||||
@@ -10,7 +10,7 @@ interface I {
|
||||
}
|
||||
|
||||
class C {
|
||||
x?: number; // error
|
||||
x?: number; // ok
|
||||
}
|
||||
|
||||
interface I2<T> {
|
||||
@@ -18,7 +18,7 @@ interface I2<T> {
|
||||
}
|
||||
|
||||
class C2<T> {
|
||||
x?: T; // error
|
||||
x?: T; // ok
|
||||
}
|
||||
|
||||
var b = {
|
||||
|
||||
147
tests/baselines/reference/optionalMethods.js
Normal file
147
tests/baselines/reference/optionalMethods.js
Normal file
@@ -0,0 +1,147 @@
|
||||
//// [optionalMethods.ts]
|
||||
|
||||
interface Foo {
|
||||
a: number;
|
||||
b?: number;
|
||||
f(): number;
|
||||
g?(): number;
|
||||
}
|
||||
|
||||
function test1(x: Foo) {
|
||||
x.a;
|
||||
x.b;
|
||||
x.f;
|
||||
x.g;
|
||||
let f1 = x.f();
|
||||
let g1 = x.g && x.g();
|
||||
let g2 = x.g ? x.g() : 0;
|
||||
}
|
||||
|
||||
class Bar {
|
||||
a: number;
|
||||
b?: number;
|
||||
c? = 2;
|
||||
constructor(public d?: number, public e = 10) {}
|
||||
f() {
|
||||
return 1;
|
||||
}
|
||||
g?(): number; // Body of optional method can be omitted
|
||||
h?() {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
function test2(x: Bar) {
|
||||
x.a;
|
||||
x.b;
|
||||
x.c;
|
||||
x.d;
|
||||
x.e;
|
||||
x.f;
|
||||
x.g;
|
||||
let f1 = x.f();
|
||||
let g1 = x.g && x.g();
|
||||
let g2 = x.g ? x.g() : 0;
|
||||
let h1 = x.h && x.h();
|
||||
let h2 = x.h ? x.h() : 0;
|
||||
}
|
||||
|
||||
class Base {
|
||||
a?: number;
|
||||
f?(): number;
|
||||
}
|
||||
|
||||
class Derived extends Base {
|
||||
a = 1;
|
||||
f(): number { return 1; }
|
||||
}
|
||||
|
||||
|
||||
//// [optionalMethods.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
function test1(x) {
|
||||
x.a;
|
||||
x.b;
|
||||
x.f;
|
||||
x.g;
|
||||
var f1 = x.f();
|
||||
var g1 = x.g && x.g();
|
||||
var g2 = x.g ? x.g() : 0;
|
||||
}
|
||||
var Bar = (function () {
|
||||
function Bar(d, e) {
|
||||
if (e === void 0) { e = 10; }
|
||||
this.d = d;
|
||||
this.e = e;
|
||||
this.c = 2;
|
||||
}
|
||||
Bar.prototype.f = function () {
|
||||
return 1;
|
||||
};
|
||||
Bar.prototype.h = function () {
|
||||
return 2;
|
||||
};
|
||||
return Bar;
|
||||
}());
|
||||
function test2(x) {
|
||||
x.a;
|
||||
x.b;
|
||||
x.c;
|
||||
x.d;
|
||||
x.e;
|
||||
x.f;
|
||||
x.g;
|
||||
var f1 = x.f();
|
||||
var g1 = x.g && x.g();
|
||||
var g2 = x.g ? x.g() : 0;
|
||||
var h1 = x.h && x.h();
|
||||
var h2 = x.h ? x.h() : 0;
|
||||
}
|
||||
var Base = (function () {
|
||||
function Base() {
|
||||
}
|
||||
return Base;
|
||||
}());
|
||||
var Derived = (function (_super) {
|
||||
__extends(Derived, _super);
|
||||
function Derived() {
|
||||
_super.apply(this, arguments);
|
||||
this.a = 1;
|
||||
}
|
||||
Derived.prototype.f = function () { return 1; };
|
||||
return Derived;
|
||||
}(Base));
|
||||
|
||||
|
||||
//// [optionalMethods.d.ts]
|
||||
interface Foo {
|
||||
a: number;
|
||||
b?: number;
|
||||
f(): number;
|
||||
g?(): number;
|
||||
}
|
||||
declare function test1(x: Foo): void;
|
||||
declare class Bar {
|
||||
d?: number;
|
||||
e: number;
|
||||
a: number;
|
||||
b?: number;
|
||||
c?: number | undefined;
|
||||
constructor(d?: number, e?: number);
|
||||
f(): number;
|
||||
g?(): number;
|
||||
h?(): number;
|
||||
}
|
||||
declare function test2(x: Bar): void;
|
||||
declare class Base {
|
||||
a?: number;
|
||||
f?(): number;
|
||||
}
|
||||
declare class Derived extends Base {
|
||||
a: number;
|
||||
f(): number;
|
||||
}
|
||||
203
tests/baselines/reference/optionalMethods.symbols
Normal file
203
tests/baselines/reference/optionalMethods.symbols
Normal file
@@ -0,0 +1,203 @@
|
||||
=== tests/cases/conformance/types/namedTypes/optionalMethods.ts ===
|
||||
|
||||
interface Foo {
|
||||
>Foo : Symbol(Foo, Decl(optionalMethods.ts, 0, 0))
|
||||
|
||||
a: number;
|
||||
>a : Symbol(Foo.a, Decl(optionalMethods.ts, 1, 15))
|
||||
|
||||
b?: number;
|
||||
>b : Symbol(Foo.b, Decl(optionalMethods.ts, 2, 14))
|
||||
|
||||
f(): number;
|
||||
>f : Symbol(Foo.f, Decl(optionalMethods.ts, 3, 15))
|
||||
|
||||
g?(): number;
|
||||
>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
}
|
||||
|
||||
function test1(x: Foo) {
|
||||
>test1 : Symbol(test1, Decl(optionalMethods.ts, 6, 1))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 8, 15))
|
||||
>Foo : Symbol(Foo, Decl(optionalMethods.ts, 0, 0))
|
||||
|
||||
x.a;
|
||||
>x.a : Symbol(Foo.a, Decl(optionalMethods.ts, 1, 15))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 8, 15))
|
||||
>a : Symbol(Foo.a, Decl(optionalMethods.ts, 1, 15))
|
||||
|
||||
x.b;
|
||||
>x.b : Symbol(Foo.b, Decl(optionalMethods.ts, 2, 14))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 8, 15))
|
||||
>b : Symbol(Foo.b, Decl(optionalMethods.ts, 2, 14))
|
||||
|
||||
x.f;
|
||||
>x.f : Symbol(Foo.f, Decl(optionalMethods.ts, 3, 15))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 8, 15))
|
||||
>f : Symbol(Foo.f, Decl(optionalMethods.ts, 3, 15))
|
||||
|
||||
x.g;
|
||||
>x.g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 8, 15))
|
||||
>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
|
||||
let f1 = x.f();
|
||||
>f1 : Symbol(f1, Decl(optionalMethods.ts, 13, 7))
|
||||
>x.f : Symbol(Foo.f, Decl(optionalMethods.ts, 3, 15))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 8, 15))
|
||||
>f : Symbol(Foo.f, Decl(optionalMethods.ts, 3, 15))
|
||||
|
||||
let g1 = x.g && x.g();
|
||||
>g1 : Symbol(g1, Decl(optionalMethods.ts, 14, 7))
|
||||
>x.g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 8, 15))
|
||||
>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
>x.g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 8, 15))
|
||||
>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
|
||||
let g2 = x.g ? x.g() : 0;
|
||||
>g2 : Symbol(g2, Decl(optionalMethods.ts, 15, 7))
|
||||
>x.g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 8, 15))
|
||||
>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
>x.g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 8, 15))
|
||||
>g : Symbol(Foo.g, Decl(optionalMethods.ts, 4, 16))
|
||||
}
|
||||
|
||||
class Bar {
|
||||
>Bar : Symbol(Bar, Decl(optionalMethods.ts, 16, 1))
|
||||
|
||||
a: number;
|
||||
>a : Symbol(Bar.a, Decl(optionalMethods.ts, 18, 11))
|
||||
|
||||
b?: number;
|
||||
>b : Symbol(Bar.b, Decl(optionalMethods.ts, 19, 14))
|
||||
|
||||
c? = 2;
|
||||
>c : Symbol(Bar.c, Decl(optionalMethods.ts, 20, 15))
|
||||
|
||||
constructor(public d?: number, public e = 10) {}
|
||||
>d : Symbol(Bar.d, Decl(optionalMethods.ts, 22, 16))
|
||||
>e : Symbol(Bar.e, Decl(optionalMethods.ts, 22, 34))
|
||||
|
||||
f() {
|
||||
>f : Symbol(Bar.f, Decl(optionalMethods.ts, 22, 52))
|
||||
|
||||
return 1;
|
||||
}
|
||||
g?(): number; // Body of optional method can be omitted
|
||||
>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
|
||||
h?() {
|
||||
>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17))
|
||||
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
function test2(x: Bar) {
|
||||
>test2 : Symbol(test2, Decl(optionalMethods.ts, 30, 1))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>Bar : Symbol(Bar, Decl(optionalMethods.ts, 16, 1))
|
||||
|
||||
x.a;
|
||||
>x.a : Symbol(Bar.a, Decl(optionalMethods.ts, 18, 11))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>a : Symbol(Bar.a, Decl(optionalMethods.ts, 18, 11))
|
||||
|
||||
x.b;
|
||||
>x.b : Symbol(Bar.b, Decl(optionalMethods.ts, 19, 14))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>b : Symbol(Bar.b, Decl(optionalMethods.ts, 19, 14))
|
||||
|
||||
x.c;
|
||||
>x.c : Symbol(Bar.c, Decl(optionalMethods.ts, 20, 15))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>c : Symbol(Bar.c, Decl(optionalMethods.ts, 20, 15))
|
||||
|
||||
x.d;
|
||||
>x.d : Symbol(Bar.d, Decl(optionalMethods.ts, 22, 16))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>d : Symbol(Bar.d, Decl(optionalMethods.ts, 22, 16))
|
||||
|
||||
x.e;
|
||||
>x.e : Symbol(Bar.e, Decl(optionalMethods.ts, 22, 34))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>e : Symbol(Bar.e, Decl(optionalMethods.ts, 22, 34))
|
||||
|
||||
x.f;
|
||||
>x.f : Symbol(Bar.f, Decl(optionalMethods.ts, 22, 52))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>f : Symbol(Bar.f, Decl(optionalMethods.ts, 22, 52))
|
||||
|
||||
x.g;
|
||||
>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
|
||||
let f1 = x.f();
|
||||
>f1 : Symbol(f1, Decl(optionalMethods.ts, 40, 7))
|
||||
>x.f : Symbol(Bar.f, Decl(optionalMethods.ts, 22, 52))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>f : Symbol(Bar.f, Decl(optionalMethods.ts, 22, 52))
|
||||
|
||||
let g1 = x.g && x.g();
|
||||
>g1 : Symbol(g1, Decl(optionalMethods.ts, 41, 7))
|
||||
>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
|
||||
let g2 = x.g ? x.g() : 0;
|
||||
>g2 : Symbol(g2, Decl(optionalMethods.ts, 42, 7))
|
||||
>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
>x.g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>g : Symbol(Bar.g, Decl(optionalMethods.ts, 25, 5))
|
||||
|
||||
let h1 = x.h && x.h();
|
||||
>h1 : Symbol(h1, Decl(optionalMethods.ts, 43, 7))
|
||||
>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17))
|
||||
>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17))
|
||||
|
||||
let h2 = x.h ? x.h() : 0;
|
||||
>h2 : Symbol(h2, Decl(optionalMethods.ts, 44, 7))
|
||||
>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17))
|
||||
>x.h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17))
|
||||
>x : Symbol(x, Decl(optionalMethods.ts, 32, 15))
|
||||
>h : Symbol(Bar.h, Decl(optionalMethods.ts, 26, 17))
|
||||
}
|
||||
|
||||
class Base {
|
||||
>Base : Symbol(Base, Decl(optionalMethods.ts, 45, 1))
|
||||
|
||||
a?: number;
|
||||
>a : Symbol(Base.a, Decl(optionalMethods.ts, 47, 12))
|
||||
|
||||
f?(): number;
|
||||
>f : Symbol(Base.f, Decl(optionalMethods.ts, 48, 15))
|
||||
}
|
||||
|
||||
class Derived extends Base {
|
||||
>Derived : Symbol(Derived, Decl(optionalMethods.ts, 50, 1))
|
||||
>Base : Symbol(Base, Decl(optionalMethods.ts, 45, 1))
|
||||
|
||||
a = 1;
|
||||
>a : Symbol(Derived.a, Decl(optionalMethods.ts, 52, 28))
|
||||
|
||||
f(): number { return 1; }
|
||||
>f : Symbol(Derived.f, Decl(optionalMethods.ts, 53, 10))
|
||||
}
|
||||
|
||||
226
tests/baselines/reference/optionalMethods.types
Normal file
226
tests/baselines/reference/optionalMethods.types
Normal file
@@ -0,0 +1,226 @@
|
||||
=== tests/cases/conformance/types/namedTypes/optionalMethods.ts ===
|
||||
|
||||
interface Foo {
|
||||
>Foo : Foo
|
||||
|
||||
a: number;
|
||||
>a : number
|
||||
|
||||
b?: number;
|
||||
>b : number | undefined
|
||||
|
||||
f(): number;
|
||||
>f : () => number
|
||||
|
||||
g?(): number;
|
||||
>g : (() => number) | undefined
|
||||
}
|
||||
|
||||
function test1(x: Foo) {
|
||||
>test1 : (x: Foo) => void
|
||||
>x : Foo
|
||||
>Foo : Foo
|
||||
|
||||
x.a;
|
||||
>x.a : number
|
||||
>x : Foo
|
||||
>a : number
|
||||
|
||||
x.b;
|
||||
>x.b : number | undefined
|
||||
>x : Foo
|
||||
>b : number | undefined
|
||||
|
||||
x.f;
|
||||
>x.f : () => number
|
||||
>x : Foo
|
||||
>f : () => number
|
||||
|
||||
x.g;
|
||||
>x.g : (() => number) | undefined
|
||||
>x : Foo
|
||||
>g : (() => number) | undefined
|
||||
|
||||
let f1 = x.f();
|
||||
>f1 : number
|
||||
>x.f() : number
|
||||
>x.f : () => number
|
||||
>x : Foo
|
||||
>f : () => number
|
||||
|
||||
let g1 = x.g && x.g();
|
||||
>g1 : number | undefined
|
||||
>x.g && x.g() : number | undefined
|
||||
>x.g : (() => number) | undefined
|
||||
>x : Foo
|
||||
>g : (() => number) | undefined
|
||||
>x.g() : number
|
||||
>x.g : () => number
|
||||
>x : Foo
|
||||
>g : () => number
|
||||
|
||||
let g2 = x.g ? x.g() : 0;
|
||||
>g2 : number
|
||||
>x.g ? x.g() : 0 : number
|
||||
>x.g : (() => number) | undefined
|
||||
>x : Foo
|
||||
>g : (() => number) | undefined
|
||||
>x.g() : number
|
||||
>x.g : () => number
|
||||
>x : Foo
|
||||
>g : () => number
|
||||
>0 : number
|
||||
}
|
||||
|
||||
class Bar {
|
||||
>Bar : Bar
|
||||
|
||||
a: number;
|
||||
>a : number
|
||||
|
||||
b?: number;
|
||||
>b : number | undefined
|
||||
|
||||
c? = 2;
|
||||
>c : number | undefined
|
||||
>2 : number
|
||||
|
||||
constructor(public d?: number, public e = 10) {}
|
||||
>d : number | undefined
|
||||
>e : number
|
||||
>10 : number
|
||||
|
||||
f() {
|
||||
>f : () => number
|
||||
|
||||
return 1;
|
||||
>1 : number
|
||||
}
|
||||
g?(): number; // Body of optional method can be omitted
|
||||
>g : (() => number) | undefined
|
||||
|
||||
h?() {
|
||||
>h : (() => number) | undefined
|
||||
|
||||
return 2;
|
||||
>2 : number
|
||||
}
|
||||
}
|
||||
|
||||
function test2(x: Bar) {
|
||||
>test2 : (x: Bar) => void
|
||||
>x : Bar
|
||||
>Bar : Bar
|
||||
|
||||
x.a;
|
||||
>x.a : number
|
||||
>x : Bar
|
||||
>a : number
|
||||
|
||||
x.b;
|
||||
>x.b : number | undefined
|
||||
>x : Bar
|
||||
>b : number | undefined
|
||||
|
||||
x.c;
|
||||
>x.c : number | undefined
|
||||
>x : Bar
|
||||
>c : number | undefined
|
||||
|
||||
x.d;
|
||||
>x.d : number | undefined
|
||||
>x : Bar
|
||||
>d : number | undefined
|
||||
|
||||
x.e;
|
||||
>x.e : number
|
||||
>x : Bar
|
||||
>e : number
|
||||
|
||||
x.f;
|
||||
>x.f : () => number
|
||||
>x : Bar
|
||||
>f : () => number
|
||||
|
||||
x.g;
|
||||
>x.g : (() => number) | undefined
|
||||
>x : Bar
|
||||
>g : (() => number) | undefined
|
||||
|
||||
let f1 = x.f();
|
||||
>f1 : number
|
||||
>x.f() : number
|
||||
>x.f : () => number
|
||||
>x : Bar
|
||||
>f : () => number
|
||||
|
||||
let g1 = x.g && x.g();
|
||||
>g1 : number | undefined
|
||||
>x.g && x.g() : number | undefined
|
||||
>x.g : (() => number) | undefined
|
||||
>x : Bar
|
||||
>g : (() => number) | undefined
|
||||
>x.g() : number
|
||||
>x.g : () => number
|
||||
>x : Bar
|
||||
>g : () => number
|
||||
|
||||
let g2 = x.g ? x.g() : 0;
|
||||
>g2 : number
|
||||
>x.g ? x.g() : 0 : number
|
||||
>x.g : (() => number) | undefined
|
||||
>x : Bar
|
||||
>g : (() => number) | undefined
|
||||
>x.g() : number
|
||||
>x.g : () => number
|
||||
>x : Bar
|
||||
>g : () => number
|
||||
>0 : number
|
||||
|
||||
let h1 = x.h && x.h();
|
||||
>h1 : number | undefined
|
||||
>x.h && x.h() : number | undefined
|
||||
>x.h : (() => number) | undefined
|
||||
>x : Bar
|
||||
>h : (() => number) | undefined
|
||||
>x.h() : number
|
||||
>x.h : () => number
|
||||
>x : Bar
|
||||
>h : () => number
|
||||
|
||||
let h2 = x.h ? x.h() : 0;
|
||||
>h2 : number
|
||||
>x.h ? x.h() : 0 : number
|
||||
>x.h : (() => number) | undefined
|
||||
>x : Bar
|
||||
>h : (() => number) | undefined
|
||||
>x.h() : number
|
||||
>x.h : () => number
|
||||
>x : Bar
|
||||
>h : () => number
|
||||
>0 : number
|
||||
}
|
||||
|
||||
class Base {
|
||||
>Base : Base
|
||||
|
||||
a?: number;
|
||||
>a : number | undefined
|
||||
|
||||
f?(): number;
|
||||
>f : (() => number) | undefined
|
||||
}
|
||||
|
||||
class Derived extends Base {
|
||||
>Derived : Derived
|
||||
>Base : Base
|
||||
|
||||
a = 1;
|
||||
>a : number
|
||||
>1 : number
|
||||
|
||||
f(): number { return 1; }
|
||||
>f : () => number
|
||||
>1 : number
|
||||
}
|
||||
|
||||
58
tests/cases/conformance/types/namedTypes/optionalMethods.ts
Normal file
58
tests/cases/conformance/types/namedTypes/optionalMethods.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
// @strictNullChecks: true
|
||||
// @declaration: true
|
||||
|
||||
interface Foo {
|
||||
a: number;
|
||||
b?: number;
|
||||
f(): number;
|
||||
g?(): number;
|
||||
}
|
||||
|
||||
function test1(x: Foo) {
|
||||
x.a;
|
||||
x.b;
|
||||
x.f;
|
||||
x.g;
|
||||
let f1 = x.f();
|
||||
let g1 = x.g && x.g();
|
||||
let g2 = x.g ? x.g() : 0;
|
||||
}
|
||||
|
||||
class Bar {
|
||||
a: number;
|
||||
b?: number;
|
||||
c? = 2;
|
||||
constructor(public d?: number, public e = 10) {}
|
||||
f() {
|
||||
return 1;
|
||||
}
|
||||
g?(): number; // Body of optional method can be omitted
|
||||
h?() {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
function test2(x: Bar) {
|
||||
x.a;
|
||||
x.b;
|
||||
x.c;
|
||||
x.d;
|
||||
x.e;
|
||||
x.f;
|
||||
x.g;
|
||||
let f1 = x.f();
|
||||
let g1 = x.g && x.g();
|
||||
let g2 = x.g ? x.g() : 0;
|
||||
let h1 = x.h && x.h();
|
||||
let h2 = x.h ? x.h() : 0;
|
||||
}
|
||||
|
||||
class Base {
|
||||
a?: number;
|
||||
f?(): number;
|
||||
}
|
||||
|
||||
class Derived extends Base {
|
||||
a = 1;
|
||||
f(): number { return 1; }
|
||||
}
|
||||
@@ -9,7 +9,7 @@ interface I {
|
||||
}
|
||||
|
||||
class C {
|
||||
x?: number; // error
|
||||
x?: number; // ok
|
||||
}
|
||||
|
||||
interface I2<T> {
|
||||
@@ -17,7 +17,7 @@ interface I2<T> {
|
||||
}
|
||||
|
||||
class C2<T> {
|
||||
x?: T; // error
|
||||
x?: T; // ok
|
||||
}
|
||||
|
||||
var b = {
|
||||
|
||||
Reference in New Issue
Block a user