diff --git a/doc/spec.md b/doc/spec.md index fa69d32105663..e9f84933c2e15 100644 --- a/doc/spec.md +++ b/doc/spec.md @@ -258,8 +258,8 @@ var i = 0; TypeScript will infer from the following function definition that the function f has return type string. ```TypeScript -function f() { - return "hello"; +function f() { + return "hello"; } ``` @@ -270,19 +270,19 @@ To benefit from this inference, a programmer can use the TypeScript language ser In this example, the programmer benefits from type inference without providing type annotations. Some beneficial tools, however, do require the programmer to provide type annotations. In TypeScript, we can express a parameter requirement as in the following code fragment. ```TypeScript -function f(s: string) { - return s; +function f(s: string) { + return s; } -f({}); // Error +f({}); // Error f("hello"); // Ok ``` This optional type annotation on the parameter 's' lets the TypeScript type checker know that the programmer expects parameter 's' to be of type 'string'. Within the body of function 'f', tools can assume 's' is of type 'string' and provide operator type checking and member completion consistent with this assumption. Tools can also signal an error on the first call to 'f', because 'f' expects a string, not an object, as its parameter. For the function 'f', the TypeScript compiler will emit the following JavaScript code: ```TypeScript -function f(s) { - return s; +function f(s) { + return s; } ``` @@ -293,7 +293,7 @@ In the JavaScript output, all type annotations have been erased. In general, Typ An ambient declaration introduces a variable into a TypeScript scope, but has zero impact on the emitted JavaScript program. Programmers can use ambient declarations to tell the TypeScript compiler that some other component will supply a variable. For example, by default the TypeScript compiler will print an error for uses of undefined variables. To add some of the common variables defined by browsers, a TypeScript programmer can use ambient declarations. The following example declares the 'document' object supplied by browsers. Because the declaration does not specify a type, the type 'any' is inferred. The type 'any' means that a tool can assume nothing about the shape or behavior of the document object. Some of the examples below will illustrate how programmers can use types to further characterize the expected behavior of an object. ```TypeScript -declare var document; +declare var document; document.title = "Hello"; // Ok because document has been declared ``` @@ -314,16 +314,16 @@ Function expressions are a powerful feature of JavaScript. They enable function TypeScript function types make it possible for programmers to express the expected *signature* of a function. A function signature is a sequence of parameter types plus a return type. The following example uses function types to express the callback signature requirements of an asynchronous voting mechanism. ```TypeScript -function vote(candidate: string, callback: (result: string) => any) { - // ... +function vote(candidate: string, callback: (result: string) => any) { + // ... } -vote("BigPig", - function(result: string) { - if (result === "BigPig") { - // ... - } - } +vote("BigPig", + function(result: string) { + if (result === "BigPig") { + // ... + } + } ); ``` @@ -342,25 +342,25 @@ Section [3.9.2](#3.9.2) provides additional information about function types. TypeScript programmers use *object types* to declare their expectations of object behavior. The following code uses an *object type literal* to specify the return type of the 'MakePoint' function. ```TypeScript -var MakePoint: () => { - x: number; y: number; +var MakePoint: () => { + x: number; y: number; }; ``` Programmers can give names to object types; we call named object types *interfaces*. For example, in the following code, an interface declares one required field (name) and one optional field (favoriteColor). ```TypeScript -interface Friend { - name: string; - favoriteColor?: string; +interface Friend { + name: string; + favoriteColor?: string; } -function add(friend: Friend) { - var name = friend.name; +function add(friend: Friend) { + var name = friend.name; } -add({ name: "Fred" }); // Ok -add({ favoriteColor: "blue" }); // Error, name required +add({ name: "Fred" }); // Ok +add({ favoriteColor: "blue" }); // Error, name required add({ name: "Jill", favoriteColor: "green" }); // Ok ``` @@ -369,27 +369,27 @@ TypeScript object types model the diversity of behaviors that a JavaScript objec The following code fragment captures a small subset of jQuery behavior, just enough to use jQuery in a simple way. ```TypeScript -interface JQuery { - text(content: string); -} - -interface JQueryStatic { - get(url: string, callback: (data: string) => any); - (query: string): JQuery; +interface JQuery { + text(content: string); +} + +interface JQueryStatic { + get(url: string, callback: (data: string) => any); + (query: string): JQuery; } declare var $: JQueryStatic; -$.get("http://mysite.org/divContent", - function (data: string) { - $("div").text(data); - } +$.get("http://mysite.org/divContent", + function (data: string) { + $("div").text(data); + } ); ``` The 'JQueryStatic' interface references another interface: 'JQuery'. This interface represents a collection of one or more DOM elements. The jQuery library can perform many operations on such a collection, but in this example the jQuery client only needs to know that it can set the text content of each jQuery element in a collection by passing a string to the 'text' method. The 'JQueryStatic' interface also contains a method, 'get', that performs an Ajax get operation on the provided URL and arranges to invoke the provided callback upon receipt of a response. -Finally, the 'JQueryStatic' interface contains a bare function signature +Finally, the 'JQueryStatic' interface contains a bare function signature ```TypeScript (query: string): JQuery; @@ -398,8 +398,8 @@ Finally, the 'JQueryStatic' interface contains a bare function signature The bare signature indicates that instances of the interface are callable. This example illustrates that TypeScript function types are just special cases of TypeScript object types. Specifically, function types are object types that contain one or more call signatures. For this reason we can write any function type as an object type literal. The following example uses both forms to describe the same type. ```TypeScript -var f: { (): string; }; -var sameType: () => string = f; // Ok +var f: { (): string; }; +var sameType: () => string = f; // Ok var nope: () => number = sameType; // Error: type mismatch ``` @@ -422,22 +422,22 @@ Section [3.3](#3.3) provides additional information about object types. Object types are compared *structurally*. For example, in the code fragment below, class 'CPoint' matches interface 'Point' because 'CPoint' has all of the required members of 'Point'. A class may optionally declare that it implements an interface, so that the compiler will check the declaration for structural compatibility. The example also illustrates that an object type can match the type inferred from an object literal, as long as the object literal supplies all of the required members. ```TypeScript -interface Point { - x: number; - y: number; +interface Point { + x: number; + y: number; } -function getX(p: Point) { - return p.x; +function getX(p: Point) { + return p.x; } -class CPoint { - x: number; - y: number; - constructor(x: number, y: number) { - this.x = x; - this.y = y; - } +class CPoint { + x: number; + y: number; + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } } getX(new CPoint(0, 0)); // Ok, fields match @@ -454,8 +454,8 @@ See section [3.11](#3.11) for more information about type comparisons. Ordinarily, TypeScript type inference proceeds "bottom-up": from the leaves of an expression tree to its root. In the following example, TypeScript infers 'number' as the return type of the function 'mul' by flowing type information bottom up in the return expression. ```TypeScript -function mul(a: number, b: number) { - return a * b; +function mul(a: number, b: number) { + return a * b; } ``` @@ -464,10 +464,10 @@ For variables and parameters without a type annotation or a default value, TypeS However, in some limited contexts, inference proceeds "top-down" from the context of an expression. Where this happens, it is called contextual typing. Contextual typing helps tools provide excellent information when a programmer is using a type but may not know all of the details of the type. For example, in the jQuery example, above, the programmer supplies a function expression as the second parameter to the 'get' method. During typing of that expression, tools can assume that the type of the function expression is as given in the 'get' signature and can provide a template that includes parameter names and types. ```TypeScript -$.get("http://mysite.org/divContent", - function (data) { - $("div").text(data); // TypeScript infers data is a string - } +$.get("http://mysite.org/divContent", + function (data) { + $("div").text(data); // TypeScript infers data is a string + } ); ``` @@ -482,36 +482,36 @@ JavaScript practice has two very common design patterns: the module pattern and This section and the namespace section below will show how TypeScript emits consistent, idiomatic JavaScript when emitting ECMAScript 3 or 5 compliant code for classes and namespaces. The goal of TypeScript's translation is to emit exactly what a programmer would type when implementing a class or namespace unaided by a tool. This section will also describe how TypeScript infers a type for each class declaration. We'll start with a simple BankAccount class. ```TypeScript -class BankAccount { - balance = 0; - deposit(credit: number) { - this.balance += credit; - return this.balance; - } -} +class BankAccount { + balance = 0; + deposit(credit: number) { + this.balance += credit; + return this.balance; + } +} ``` This class generates the following JavaScript code. ```TypeScript -var BankAccount = (function () { - function BankAccount() { - this.balance = 0; - } - BankAccount.prototype.deposit = function(credit) { - this.balance += credit; - return this.balance; - }; - return BankAccount; +var BankAccount = (function () { + function BankAccount() { + this.balance = 0; + } + BankAccount.prototype.deposit = function(credit) { + this.balance += credit; + return this.balance; + }; + return BankAccount; })(); ``` This TypeScript class declaration creates a variable named 'BankAccount' whose value is the constructor function for 'BankAccount' instances. This declaration also creates an instance type of the same name. If we were to write this type as an interface it would look like the following. ```TypeScript -interface BankAccount { - balance: number; - deposit(credit: number): number; +interface BankAccount { + balance: number; + deposit(credit: number): number; } ``` @@ -526,28 +526,28 @@ The function signature is prefixed with the keyword 'new' indicating that the 'B If we want to start our bank account with an initial balance, we can add to the 'BankAccount' class a constructor declaration. ```TypeScript -class BankAccount { - balance: number; - constructor(initially: number) { - this.balance = initially; - } - deposit(credit: number) { - this.balance += credit; - return this.balance; - } +class BankAccount { + balance: number; + constructor(initially: number) { + this.balance = initially; + } + deposit(credit: number) { + this.balance += credit; + return this.balance; + } } ``` This version of the 'BankAccount' class requires us to introduce a constructor parameter and then assign it to the 'balance' field. To simplify this common case, TypeScript accepts the following shorthand syntax. ```TypeScript -class BankAccount { - constructor(public balance: number) { - } - deposit(credit: number) { - this.balance += credit; - return this.balance; - } +class BankAccount { + constructor(public balance: number) { + } + deposit(credit: number) { + this.balance += credit; + return this.balance; + } } ``` @@ -556,19 +556,19 @@ The 'public' keyword denotes that the constructor parameter is to be retained as TypeScript classes also support inheritance, as in the following example.* * ```TypeScript -class CheckingAccount extends BankAccount { - constructor(balance: number) { - super(balance); - } - writeCheck(debit: number) { - this.balance -= debit; - } +class CheckingAccount extends BankAccount { + constructor(balance: number) { + super(balance); + } + writeCheck(debit: number) { + this.balance -= debit; + } } ``` -In this example, the class 'CheckingAccount' *derives* from class 'BankAccount'. The constructor for 'CheckingAccount' calls the constructor for class 'BankAccount' using the 'super' keyword. In the emitted JavaScript code, the prototype of 'CheckingAccount' will chain to the prototype of 'BankAccount'. +In this example, the class 'CheckingAccount' *derives* from class 'BankAccount'. The constructor for 'CheckingAccount' calls the constructor for class 'BankAccount' using the 'super' keyword. In the emitted JavaScript code, the prototype of 'CheckingAccount' will chain to the prototype of 'BankAccount'. -TypeScript classes may also specify static members. Static class members become properties of the class constructor. +TypeScript classes may also specify static members. Static class members become properties of the class constructor. Section [8](#8) provides additional information about classes. @@ -577,16 +577,16 @@ Section [8](#8) provides additional information about classes. TypeScript enables programmers to summarize a set of numeric constants as an *enum type*. The example below creates an enum type to represent operators in a calculator application. ```TypeScript -const enum Operator { - ADD, - DIV, - MUL, - SUB +const enum Operator { + ADD, + DIV, + MUL, + SUB } -function compute(op: Operator, a: number, b: number) { - console.log("the operator is" + Operator[op]); - // ... +function compute(op: Operator, a: number, b: number) { + console.log("the operator is" + Operator[op]); + // ... } ``` @@ -597,28 +597,28 @@ When enums are declared with the `const` modifier, the TypeScript compiler will For example, the 'compute' function could contain a switch statement like the following. ```TypeScript -switch (op) { - case Operator.ADD: - // execute add - break; - case Operator.DIV: - // execute div - break; - // ... +switch (op) { + case Operator.ADD: + // execute add + break; + case Operator.DIV: + // execute div + break; + // ... } ``` For this switch statement, the compiler will generate the following code. ```TypeScript -switch (op) { - case 0 /* Operator.ADD */: - // execute add - break; - case 1 /* Operator.DIV */: - // execute div - break; - // ... +switch (op) { + case 0 /* Operator.ADD */: + // execute add + break; + case 1 /* Operator.DIV */: + // execute div + break; + // ... } ``` @@ -635,7 +635,7 @@ JavaScript programming interfaces often include functions whose behavior is disc The following code fragment uses this feature. Because the 'span' variable is inferred to have the type 'HTMLSpanElement', the code can reference without static error the 'isMultiline' property of 'span'. ```TypeScript -var span = document.createElement("span"); +var span = document.createElement("span"); span.isMultiLine = false; // OK: HTMLSpanElement has isMultiline property ``` @@ -652,10 +652,10 @@ Like overloading on string parameters, *generic types* make it easier for TypeSc To illustrate this, let's take a look at part of the TypeScript interface for the built-in JavaScript array type. You can find this interface in the 'lib.d.ts' file that accompanies a TypeScript distribution. ```TypeScript -interface Array { - reverse(): T[]; - sort(compareFn?: (a: T, b: T) => number): T[]; - // ... +interface Array { + reverse(): T[]; + sort(compareFn?: (a: T, b: T) => number): T[]; + // ... } ``` @@ -672,9 +672,9 @@ The map method, invoked on an array 'a' with element type 'T', will apply functi The TypeScript compiler can often infer generic method parameters, making it unnecessary for the programmer to explicitly provide them. In the following example, the compiler infers that parameter 'U' of the map method has type 'string', because the function passed to map returns a string. ```TypeScript -function numberToString(a: number[]) { - var stringArray = a.map(v => v.toString()); - return stringArray; +function numberToString(a: number[]) { + var stringArray = a.map(v => v.toString()); + return stringArray; } ``` @@ -683,27 +683,27 @@ The compiler infers in this example that the 'numberToString' function returns a In TypeScript, classes can also have type parameters. The following code declares a class that implements a linked list of items of type 'T'. This code illustrates how programmers can *constrain* type parameters to extend a specific type. In this case, the items on the list must extend the type 'NamedItem'. This enables the programmer to implement the 'log' function, which logs the name of the item. ```TypeScript -interface NamedItem { - name: string; +interface NamedItem { + name: string; } -class List { +class List { next: List = null; - constructor(public item: T) { + constructor(public item: T) { } - insertAfter(item: T) { - var temp = this.next; - this.next = new List(item); - this.next.next = temp; + insertAfter(item: T) { + var temp = this.next; + this.next = new List(item); + this.next.next = temp; } - log() { - console.log(this.item.name); + log() { + console.log(this.item.name); } - // ... + // ... } ``` @@ -713,17 +713,17 @@ Section [3.7](#3.7) provides further information about generic types. Classes and interfaces support large-scale JavaScript development by providing a mechanism for describing how to use a software component that can be separated from that component's implementation. TypeScript enforces *encapsulation* of implementation in classes at design time (by restricting use of private and protected members), but cannot enforce encapsulation at runtime because all object properties are accessible at runtime. Future versions of JavaScript may provide *private names* which would enable runtime enforcement of private and protected members. -In JavaScript, a very common way to enforce encapsulation at runtime is to use the module pattern: encapsulate private fields and methods using closure variables. The module pattern is a natural way to provide organizational structure and dynamic loading options by drawing a boundary around a software component. The module pattern can also provide the ability to introduce namespaces, avoiding use of the global namespace for most software components. +In JavaScript, a very common way to enforce encapsulation at runtime is to use the module pattern: encapsulate private fields and methods using closure variables. The module pattern is a natural way to provide organizational structure and dynamic loading options by drawing a boundary around a software component. The module pattern can also provide the ability to introduce namespaces, avoiding use of the global namespace for most software components. The following example illustrates the JavaScript module pattern. ```TypeScript -(function(exports) { - var key = generateSecretKey(); - function sendMessage(message) { - sendSecureMessage(message, key); - } - exports.sendMessage = sendMessage; +(function(exports) { + var key = generateSecretKey(); + function sendMessage(message) { + sendSecureMessage(message, key); + } + exports.sendMessage = sendMessage; })(MessageModule); ``` @@ -736,22 +736,22 @@ TypeScript namespaces provide a mechanism for succinctly expressing the module p The following example shows the definition and use of a simple namespace. ```TypeScript -namespace M { - var s = "hello"; - export function f() { - return s; - } +namespace M { + var s = "hello"; + export function f() { + return s; + } } -M.f(); +M.f(); M.s; // Error, s is not exported ``` In this example, variable 's' is a private feature of the namespace, but function 'f' is exported from the namespace and accessible to code outside of the namespace. If we were to describe the effect of namespace 'M' in terms of interfaces and variables, we would write ```TypeScript -interface M { - f(): string; +interface M { + f(): string; } var M: M; @@ -762,13 +762,13 @@ The interface 'M' summarizes the externally visible behavior of namespace 'M'. I The TypeScript compiler emits the following JavaScript code for the namespace: ```TypeScript -var M; -(function(M) { - var s = "hello"; - function f() { - return s; - } - M.f = f; +var M; +(function(M) { + var s = "hello"; + function f() { + return s; + } + M.f = f; })(M || (M = {})); ``` @@ -788,10 +788,10 @@ The remainder of this document is the formal specification of the TypeScript pro The syntactic grammar added by TypeScript language is specified throughout this document using the existing conventions and production names of the ECMAScript grammar. In places where TypeScript augments an existing grammar production it is so noted. For example: -  *Declaration:* *( Modified )* -   … -   *InterfaceDeclaration* -   *TypeAliasDeclaration* +  *Declaration:* *( Modified )* +   … +   *InterfaceDeclaration* +   *TypeAliasDeclaration*    *EnumDeclaration* The '*( Modified )*' annotation indicates that an existing grammar production is being replaced, and the '…' references the contents of the original grammar production. @@ -814,55 +814,56 @@ Most commonly, names are written to conform with the *Identifier* production, wh The following keywords are reserved and cannot be used as an *Identifier*: ```TypeScript -break case catch class -const continue debugger default -delete do else enum -export extends false finally -for function if import -in instanceof new null -return super switch this -throw true try typeof +break case catch class +const continue debugger default +delete do else enum +export extends false finally +for function if import +in instanceof new null +return super switch this +throw true try typeof var void while with ``` The following keywords cannot be used as identifiers in strict mode code, but are otherwise not restricted: ```TypeScript -implements interface let package -private protected public static +implements interface let package +private protected public static yield ``` The following keywords cannot be used as user defined type names, but are otherwise not restricted: ```TypeScript -any boolean number string +any boolean number string symbol ``` The following keywords have special meaning in certain contexts, but are valid identifiers: ```TypeScript -abstract as async await -constructor declare from get -is module namespace of -require set type +abstract as async await +constructor declare from get +is module namespace of +override readonly require set +type ``` ### 2.2.2 Property Names The *PropertyName* production from the ECMAScript grammar is reproduced below: -  *PropertyName:* -   *LiteralPropertyName* +  *PropertyName:* +   *LiteralPropertyName*    *ComputedPropertyName* -  *LiteralPropertyName:* -   *IdentifierName* -   *StringLiteral* +  *LiteralPropertyName:* +   *IdentifierName* +   *StringLiteral*    *NumericLiteral* -  *ComputedPropertyName:* +  *ComputedPropertyName:*    `[` *AssignmentExpression* `]` A property name can be any identifier (including a reserved word), a string literal, a numeric literal, or a computed property name. String literals may be used to give properties names that are not valid identifiers, such as names containing blanks. Numeric literal property names are equivalent to string literal property names with the string representation of the numeric literal, as defined in the ECMAScript specification. @@ -882,8 +883,8 @@ In a *PropertyName* that specifies a *ComputedPropertyName*, the computed proper Below is an example of an interface that declares a property with a well-known symbol name: ```TypeScript -interface Iterable { - [Symbol.iterator](): Iterator; +interface Iterable { + [Symbol.iterator](): Iterator; } ``` @@ -898,8 +899,8 @@ var X: string; // Value named X type X = number; // Type named X -namespace X { // Namespace named X - type Y = string; +namespace X { // Namespace named X + type Y = string; } ``` @@ -908,7 +909,7 @@ A name that denotes a value has an associated type (section [3](#3)) and can be When a name with multiple meanings is referenced, the context in which the reference occurs determines the meaning. For example: ```TypeScript -var n: X; // X references type +var n: X; // X references type var s: X.Y = X; // First X references namespace, second X references value ``` @@ -926,12 +927,12 @@ Declarations introduce the following meanings for the name they declare: Below are some examples of declarations that introduce multiple meanings for a name: ```TypeScript -class C { // Value and type named C - x: string; +class C { // Value and type named C + x: string; } -namespace N { // Value and namespace named N - export var x: string; +namespace N { // Value and namespace named N + export var x: string; } ``` @@ -970,9 +971,9 @@ Interfaces, enums, and namespaces are "open ended," meaning that interface, enum Instance and static members in a class are in separate declaration spaces. Thus the following is permitted: ```TypeScript -class C { - x: number; // Instance member - static x: string; // Static member +class C { + x: number; // Instance member + static x: string; // Static member } ``` @@ -1008,17 +1009,17 @@ Note that class and interface members are never directly in scope—they can onl As the rules above imply, locally declared entities in a namespace are closer in scope than exported entities declared in other namespace declarations for the same namespace. For example: ```TypeScript -var x = 1; -namespace M { - export var x = 2; - console.log(x); // 2 -} -namespace M { - console.log(x); // 2 -} -namespace M { - var x = 3; - console.log(x); // 3 +var x = 1; +namespace M { + export var x = 2; + console.log(x); // 2 +} +namespace M { + console.log(x); // 2 +} +namespace M { + var x = 3; + console.log(x); // 3 } ``` @@ -1061,12 +1062,12 @@ The Any type is a supertype of all types, and is assignable to and from all type Some examples: ```TypeScript -var x: any; // Explicitly typed -var y; // Same as y: any +var x: any; // Explicitly typed +var y; // Same as y: any var z: { a; b; }; // Same as z: { a: any; b: any; } -function f(x) { // Same as f(x: any): void - console.log(x); +function f(x) { // Same as f(x: any): void + console.log(x); } ``` @@ -1085,9 +1086,9 @@ For purposes of determining type relationships (section [3.11](#3.11)) and acces Some examples: ```TypeScript -var x: number; // Explicitly typed -var y = 0; // Same as y: number = 0 -var z = 123.456; // Same as z: number = 123.456 +var x: number; // Explicitly typed +var y = 0; // Same as y: number = 0 +var z = 123.456; // Same as z: number = 123.456 var s = z.toFixed(2); // Property of Number interface ``` @@ -1102,8 +1103,8 @@ For purposes of determining type relationships (section [3.11](#3.11)) and acces Some examples: ```TypeScript -var b: boolean; // Explicitly typed -var yes = true; // Same as yes: boolean = true +var b: boolean; // Explicitly typed +var yes = true; // Same as yes: boolean = true var no = false; // Same as no: boolean = false ``` @@ -1118,9 +1119,9 @@ For purposes of determining type relationships (section [3.11](#3.11)) and acces Some examples: ```TypeScript -var s: string; // Explicitly typed -var empty = ""; // Same as empty: string = "" -var abc = 'abc'; // Same as abc: string = "abc" +var s: string; // Explicitly typed +var empty = ""; // Same as empty: string = "" +var abc = 'abc'; // Same as abc: string = "abc" var c = abc.charAt(2); // Property of String interface ``` @@ -1135,9 +1136,9 @@ For purposes of determining type relationships (section [3.11](#3.11)) and acces Some examples: ```TypeScript -var secretKey = Symbol(); -var obj = {}; -obj[secretKey] = "secret message"; // Use symbol as property key +var secretKey = Symbol(); +var obj = {}; +obj[secretKey] = "secret message"; // Use symbol as property key obj[Symbol.toStringTag] = "test"; // Use of well-known symbol ``` @@ -1160,8 +1161,8 @@ The Null type is a subtype of all types, except the Undefined type. This means t Some examples: ```TypeScript -var n: number = null; // Primitives can be null -var x = null; // Same as x: any = null +var n: number = null; // Primitives can be null +var x = null; // Same as x: any = null var e: Null; // Error, can't reference Null type ``` @@ -1176,8 +1177,8 @@ The undefined type is a subtype of all types. This means that `undefined` is con Some examples: ```TypeScript -var n: number; // Same as n: number = undefined -var x = undefined; // Same as x: any = undefined +var n: number; // Same as n: number = undefined +var x = undefined; // Same as x: any = undefined var e: Undefined; // Error, can't reference Undefined type ``` @@ -1223,10 +1224,10 @@ Type references (section [3.8.2](#3.8.2)) to class and interface types are class The declaration of the 'Array' interface includes a property 'length' and a numeric index signature for the element type, along with other members: ```TypeScript -interface Array { - length: number; - [x: number]: T; - // Other members +interface Array { + length: number; + [x: number]: T; + // Other members } ``` @@ -1249,11 +1250,11 @@ A type is said to be an ***array-like type*** if it is assignable (section [3.11 combines the set of properties ```TypeScript -{ - 0: T0; - 1: T1; - ... - n: Tn; +{ + 0: T0; + 1: T1; + ... + n: Tn; } ``` @@ -1262,10 +1263,10 @@ with the members of an array type whose element type is the union type (section Array literals (section [4.6](#4.6)) may be used to create values of tuple types. For example: ```TypeScript -var t: [number, string] = [3, "three"]; -var n = t[0]; // Type of n is number -var s = t[1]; // Type of s is string -var i: number; +var t: [number, string] = [3, "three"]; +var n = t[0]; // Type of n is number +var s = t[1]; // Type of s is string +var i: number; var x = t[i]; // Type of x is number | string ``` @@ -1326,12 +1327,12 @@ Type guards (section [4.24](#4.24)) may be used to narrow a union type to a more In the example ```TypeScript -var x: string | number; -var test: boolean; -x = "hello"; // Ok -x = 42; // Ok -x = test; // Error, boolean not assignable -x = test ? 5 : "five"; // Ok +var x: string | number; +var test: boolean; +x = "hello"; // Ok +x = 42; // Ok +x = test; // Error, boolean not assignable +x = test ? 5 : "five"; // Ok x = test ? 0 : false; // Error, number | boolean not assignable ``` @@ -1344,20 +1345,20 @@ var n = typeof x === "string" ? x.length : x; // Type of n is number For purposes of property access and function calls, the apparent members (section [3.11.1](#3.11.1)) of a union type are those that are present in every one of its constituent types, with types that are unions of the respective apparent members in the constituent types. The following example illustrates the merging of member types that occurs when union types are created from object types. ```TypeScript -interface A { - a: string; - b: number; +interface A { + a: string; + b: number; } -interface B { - a: number; - b: number; - c: number; +interface B { + a: number; + b: number; + c: number; } -var x: A | B; -var a = x.a; // a has type string | number -var b = x.b; // b has type number +var x: A | B; +var a = x.a; // a has type string | number +var b = x.b; // b has type number var c = x.c; // Error, no property c in union type ``` @@ -1384,36 +1385,36 @@ Similarly, intersection types have the following assignability relationships: For purposes of property access and function calls, the apparent members (section [3.11.1](#3.11.1)) of an intersection type are those that are present in one or more of its constituent types, with types that are intersections of the respective apparent members in the constituent types. The following examples illustrate the merging of member types that occurs when intersection types are created from object types. ```TypeScript -interface A { a: number } +interface A { a: number } interface B { b: number } -var ab: A & B = { a: 1, b: 1 }; -var a: A = ab; // A & B assignable to A +var ab: A & B = { a: 1, b: 1 }; +var a: A = ab; // A & B assignable to A var b: B = ab; // A & B assignable to B -interface X { p: A } +interface X { p: A } interface Y { p: B } var xy: X & Y = { p: ab }; // X & Y has property p of type A & B -type F1 = (a: string, b: string) => void; +type F1 = (a: string, b: string) => void; type F2 = (a: number, b: number) => void; -var f: F1 & F2 = (a: string | number, b: string | number) => { }; -f("hello", "world"); // Ok -f(1, 2); // Ok +var f: F1 & F2 = (a: string | number, b: string | number) => { }; +f("hello", "world"); // Ok +f(1, 2); // Ok f(1, "test"); // Error ``` The union and intersection type operators can be applied to type parameters. This capability can for example be used to model functions that merge objects: ```TypeScript -function extend(first: T, second: U): T & U { - // Extend first with properties of second +function extend(first: T, second: U): T & U { + // Extend first with properties of second } -var x = extend({ a: "hello" }, { b: 42 }); -var s = x.a; +var x = extend({ a: "hello" }, { b: 42 }); +var s = x.a; var n = x.b; ``` @@ -1429,17 +1430,17 @@ Since a type parameter represents a multitude of different type arguments, type Class, interface, type alias, and function declarations may optionally include lists of type parameters enclosed in < and > brackets. Type parameters are also permitted in call signatures of object, function, and constructor type literals. -  *TypeParameters:* +  *TypeParameters:*    `<` *TypeParameterList* `>` -  *TypeParameterList:* -   *TypeParameter* +  *TypeParameterList:* +   *TypeParameter*    *TypeParameterList* `,` *TypeParameter* -  *TypeParameter:* +  *TypeParameter:*    *BindingIdentifier* *Constraintopt* -  *Constraint:* +  *Constraint:*    `extends` *Type* Type parameter names must be unique. A compile-time error occurs if two or more type parameters in the same *TypeParameterList* have the same name. @@ -1476,14 +1477,14 @@ interface B { } A type reference (section [3.8.2](#3.8.2)) to a generic type must include a list of type arguments enclosed in angle brackets and separated by commas. Similarly, a call (section [4.15](#4.15)) to a generic function may explicitly include a type argument list instead of relying on type inference. -  *TypeArguments:* +  *TypeArguments:*    `<` *TypeArgumentList* `>` -  *TypeArgumentList:* -   *TypeArgument* +  *TypeArgumentList:* +   *TypeArgument*    *TypeArgumentList* `,` *TypeArgument* -  *TypeArgument:* +  *TypeArgument:*    *Type* Type arguments correspond one-to-one with type parameters of the generic type or function being referenced. A type argument list is required to specify exactly one type argument for each corresponding type parameter, and each type argument for a constrained type parameter is required to ***satisfy*** the constraint of that type parameter. A type argument satisfies a type parameter constraint if the type argument is assignable to (section [3.11.4](#3.11.4)) the constraint type once type arguments are substituted for type parameters. @@ -1505,19 +1506,19 @@ Every class and interface has a ***this-type*** that represents the actual type Classes and interfaces support inheritance and therefore the instance represented by `this` in a method isn't necessarily an instance of the containing class—it may in fact be an instance of a derived class or interface. To model this relationship, the this-type of a class or interface is classified as a type parameter. Unlike other type parameters, it is not possible to explicitly pass a type argument for a this-type. Instead, in a type reference to a class or interface type, the type reference *itself* is implicitly passed as a type argument for the this-type. For example: ```TypeScript -class A { - foo() { - return this; - } +class A { + foo() { + return this; + } } -class B extends A { - bar() { - return this; - } +class B extends A { + bar() { + return this; + } } -let b: B; +let b: B; let x = b.foo().bar(); // Fluent pattern works, type of x is B ``` @@ -1557,37 +1558,37 @@ is indistinguishable from the type Types are specified either by referencing their keyword or name, or by writing object type literals, array type literals, tuple type literals, function type literals, constructor type literals, or type queries. -  *Type:* -   *UnionOrIntersectionOrPrimaryType* -   *FunctionType* +  *Type:* +   *UnionOrIntersectionOrPrimaryType* +   *FunctionType*    *ConstructorType* -  *UnionOrIntersectionOrPrimaryType:* -   *UnionType* +  *UnionOrIntersectionOrPrimaryType:* +   *UnionType*    *IntersectionOrPrimaryType* -  *IntersectionOrPrimaryType:* -   *IntersectionType* +  *IntersectionOrPrimaryType:* +   *IntersectionType*    *PrimaryType* -  *PrimaryType:* -   *ParenthesizedType* -   *PredefinedType* -   *TypeReference* -   *ObjectType* -   *ArrayType* -   *TupleType* -   *TypeQuery* +  *PrimaryType:* +   *ParenthesizedType* +   *PredefinedType* +   *TypeReference* +   *ObjectType* +   *ArrayType* +   *TupleType* +   *TypeQuery*    *ThisType* -  *ParenthesizedType:* +  *ParenthesizedType:*    `(` *Type* `)` Parentheses are required around union, intersection, function, or constructor types when they are used as array element types; around union, function, or constructor types in intersection types; and around function or constructor types in union types. For example: ```TypeScript -(string | number)[] -((x: string) => string) | ((x: number) => number) +(string | number)[] +((x: string) => string) | ((x: number) => number) (A | B) & (C | D) ``` @@ -1597,12 +1598,12 @@ The different forms of type notations are described in the following sections. The `any`, `number`, `boolean`, `string`, `symbol` and `void` keywords reference the Any type and the Number, Boolean, String, Symbol, and Void primitive types respectively. -  *PredefinedType:* -   `any` -   `number` -   `boolean` -   `string` -   `symbol` +  *PredefinedType:* +   `any` +   `number` +   `boolean` +   `string` +   `symbol`    `void` The predefined type keywords are reserved and cannot be used as names of user defined types. @@ -1611,15 +1612,15 @@ The predefined type keywords are reserved and cannot be used as names of user de A type reference references a named type or type parameter through its name and, in the case of a generic type, supplies a type argument list. -  *TypeReference:* +  *TypeReference:*    *TypeName* *[no LineTerminator here]* *TypeArgumentsopt* -  *TypeName:* -   *IdentifierReference* +  *TypeName:* +   *IdentifierReference*    *NamespaceName* `.` *IdentifierReference* -  *NamespaceName:* -   *IdentifierReference* +  *NamespaceName:* +   *IdentifierReference*    *NamespaceName* `.` *IdentifierReference* A *TypeReference* consists of a *TypeName* that a references a named type or type parameter. A reference to a generic type must be followed by a list of *TypeArguments* (section [3.6.2](#3.6.2)). @@ -1643,17 +1644,17 @@ interface B extends A { b: string; } interface C extends B { c: string; } -interface G { - x: T; - y: U; +interface G { + x: T; + y: U; } -var v1: G; // Ok -var v2: G<{ a: string }, C>; // Ok, equivalent to G -var v3: G; // Error, A not valid argument for U -var v4: G, C>; // Ok -var v5: G; // Ok -var v6: G; // Error, wrong number of arguments +var v1: G; // Ok +var v2: G<{ a: string }, C>; // Ok, equivalent to G +var v3: G; // Error, A not valid argument for U +var v4: G, C>; // Ok +var v5: G; // Ok +var v6: G; // Error, wrong number of arguments var v7: G; // Error, no arguments ``` @@ -1662,9 +1663,9 @@ A type argument is simply a *Type* and may itself be a type reference to a gener As described in section [3.7](#3.7), a type reference to a generic type *G* designates a type wherein all occurrences of *G*'s type parameters have been replaced with the actual type arguments supplied in the type reference. For example, the declaration of 'v1' above is equivalent to: ```TypeScript -var v1: { - x: { a: string; } - y: { a: string; b: string; c: string }; +var v1: { + x: { a: string; } + y: { a: string; b: string; c: string }; }; ``` @@ -1672,23 +1673,23 @@ var v1: { An object type literal defines an object type by specifying the set of members that are statically considered to be present in instances of the type. Object type literals can be given names using interface declarations but are otherwise anonymous. -  *ObjectType:* +  *ObjectType:*    `{` *TypeBodyopt* `}` -  *TypeBody:* -   *TypeMemberList* `;`*opt* +  *TypeBody:* +   *TypeMemberList* `;`*opt*    *TypeMemberList* `,`*opt* -  *TypeMemberList:* -   *TypeMember* -   *TypeMemberList* `;` *TypeMember* +  *TypeMemberList:* +   *TypeMember* +   *TypeMemberList* `;` *TypeMember*    *TypeMemberList* `,` *TypeMember* -  *TypeMember:* -   *PropertySignature* -   *CallSignature* -   *ConstructSignature* -   *IndexSignature* +  *TypeMember:* +   *PropertySignature* +   *CallSignature* +   *ConstructSignature* +   *IndexSignature*    *MethodSignature* The members of an object type literal are specified as a combination of property, call, construct, index, and method signatures. Object type members are described in section [3.9](#3.9). @@ -1697,7 +1698,7 @@ The members of an object type literal are specified as a combination of property An array type literal is written as an element type followed by an open and close square bracket. -  *ArrayType:* +  *ArrayType:*    *PrimaryType* *[no LineTerminator here]* `[` `]` An array type literal references an array type (section [3.3.2](#3.3.2)) with the given element type. An array type literal is simply shorthand notation for a reference to the generic interface type 'Array' in the global namespace with the element type as a type argument. @@ -1705,14 +1706,14 @@ An array type literal references an array type (section [3.3.2](#3.3.2)) with th When union, intersection, function, or constructor types are used as array element types they must be enclosed in parentheses. For example: ```TypeScript -(string | number)[] +(string | number)[] (() => string))[] ``` Alternatively, array types can be written using the 'Array<T>' notation. For example, the types above are equivalent to ```TypeScript -Array +Array Array<() => string> ``` @@ -1720,14 +1721,14 @@ Array<() => string> A tuple type literal is written as a sequence of element types, separated by commas and enclosed in square brackets. -  *TupleType:* +  *TupleType:*    `[` *TupleElementTypes* `]` -  *TupleElementTypes:* -   *TupleElementType* +  *TupleElementTypes:* +   *TupleElementType*    *TupleElementTypes* `,` *TupleElementType* -  *TupleElementType:* +  *TupleElementType:*    *Type* A tuple type literal references a tuple type (section [3.3.3](#3.3.3)). @@ -1736,7 +1737,7 @@ A tuple type literal references a tuple type (section [3.3.3](#3.3.3)). A union type literal is written as a sequence of types separated by vertical bars. -  *UnionType:* +  *UnionType:*    *UnionOrIntersectionOrPrimaryType* `|` *IntersectionOrPrimaryType* A union type literal references a union type (section [3.4](#3.4)). @@ -1745,7 +1746,7 @@ A union type literal references a union type (section [3.4](#3.4)). An intersection type literal is written as a sequence of types separated by ampersands. -  *IntersectionType:* +  *IntersectionType:*    *IntersectionOrPrimaryType* `&` *PrimaryType* An intersection type literal references an intersection type (section [3.5](#3.5)). @@ -1754,7 +1755,7 @@ An intersection type literal references an intersection type (section [3.5](#3.5 A function type literal specifies the type parameters, regular parameters, and return type of a call signature. -  *FunctionType:* +  *FunctionType:*    *TypeParametersopt* `(` *ParameterListopt* `)` `=>` *Type* A function type literal is shorthand for an object type containing a single call signature. Specifically, a function type literal of the form @@ -1775,7 +1776,7 @@ Note that function types with multiple call or construct signatures cannot be wr A constructor type literal specifies the type parameters, regular parameters, and return type of a construct signature. -  *ConstructorType:* +  *ConstructorType:*    `new` *TypeParametersopt* `(` *ParameterListopt* `)` `=>` *Type* A constructor type literal is shorthand for an object type containing a single construct signature. Specifically, a constructor type literal of the form @@ -1796,11 +1797,11 @@ Note that constructor types with multiple construct signatures cannot be written A type query obtains the type of an expression. -  *TypeQuery:* +  *TypeQuery:*    `typeof` *TypeQueryExpression* -  *TypeQueryExpression:* -   *IdentifierReference* +  *TypeQueryExpression:* +   *IdentifierReference*    *TypeQueryExpression* `.` *IdentifierName* A type query consists of the keyword `typeof` followed by an expression. The expression is restricted to a single identifier or a sequence of identifiers separated by periods. The expression is processed as an identifier expression (section [4.3](#4.3)) or property access expression (section [4.13](#4.13)), the widened type (section [3.12](#3.12)) of which becomes the result. Similar to other static typing constructs, type queries are erased from the generated JavaScript code and add no run-time overhead. @@ -1808,7 +1809,7 @@ A type query consists of the keyword `typeof` followed by an expression. The exp Type queries are useful for capturing anonymous types that are generated by various constructs such as object literals, function declarations, and namespace declarations. For example: ```TypeScript -var a = { x: 10, y: 20 }; +var a = { x: 10, y: 20 }; var b: typeof a; ``` @@ -1817,16 +1818,16 @@ Above, 'b' is given the same type as 'a', namely `{ x: number; y: number; }`. If a declaration includes a type annotation that references the entity being declared through a circular path of type queries or type references containing type queries, the resulting type is the Any type. For example, all of the following variables are given the type Any: ```TypeScript -var c: typeof c; -var d: typeof e; -var e: typeof d; +var c: typeof c; +var d: typeof e; +var e: typeof d; var f: Array; ``` However, if a circular path of type queries includes at least one *ObjectType*, *FunctionType* or *ConstructorType*, the construct denotes a recursive type: ```TypeScript -var g: { x: typeof g; }; +var g: { x: typeof g; }; var h: () => typeof h; ``` @@ -1836,7 +1837,7 @@ Here, 'g' and 'g.x' have the same recursive type, and likewise 'h' and 'h()' hav The `this` keyword is used to reference the this-type (section [3.6.3](#3.6.3)) of a class or interface. -  *ThisType:* +  *ThisType:*    `this` The meaning of a *ThisType* depends on the closest enclosing *FunctionDeclaration*, *FunctionExpression*, *PropertyDefinition*, *ClassElement*, or *TypeMember*, known as the root declaration of the *ThisType*, as follows: @@ -1848,10 +1849,10 @@ The meaning of a *ThisType* depends on the closest enclosing *FunctionDeclaratio Note that in order to avoid ambiguities it is not possible to reference the this-type of a class or interface in a nested object type literal. In the example ```TypeScript -interface ListItem { - getHead(): this; - getTail(): this; - getHeadAndTail(): { head: this, tail: this }; // Error +interface ListItem { + getHead(): this; + getTail(): this; + getHeadAndTail(): { head: this, tail: this }; // Error } ``` @@ -1860,25 +1861,25 @@ the `this` references on the last line are in error because their root declarati ```TypeScript type HeadAndTail = { head: T, tail: T }; -interface ListItem { - getHead(): this; - getTail(): this; - getHeadAndTail(): HeadAndTail; +interface ListItem { + getHead(): this; + getTail(): this; + getHeadAndTail(): HeadAndTail; } ``` ## 3.9 Specifying Members -The members of an object type literal (section [3.8.3](#3.8.3)) are specified as a combination of property, call, construct, index, and method signatures. +The members of an object type literal (section [3.8.3](#3.8.3)) are specified as a combination of property, call, construct, index, and method signatures. ### 3.9.1 Property Signatures A property signature declares the name and type of a property member. -  *PropertySignature:* +  *PropertySignature:*    *PropertyName* `?`*opt* *TypeAnnotationopt* -  *TypeAnnotation:* +  *TypeAnnotation:*    `:` *Type* The *PropertyName* ([2.2.2](#2.2.2)) of a property signature must be unique within its containing type, and must denote a well-known symbol if it is a computed property name ([2.2.3](#2.2.3)). If the property name is followed by a question mark, the property is optional. Otherwise, the property is required. @@ -1889,7 +1890,7 @@ If a property signature omits a *TypeAnnotation*, the Any type is assumed. A call signature defines the type parameters, parameter list, and return type associated with applying a call operation (section [4.15](#4.15)) to an instance of the containing type. A type may ***overload*** call operations by defining multiple different call signatures. -  *CallSignature:* +  *CallSignature:*    *TypeParametersopt* `(` *ParameterListopt* `)` *TypeAnnotationopt* A call signature that includes *TypeParameters* (section [3.6.1](#3.6.1)) is called a ***generic call signature***. Conversely, a call signature with no *TypeParameters* is called a non-generic call signature. @@ -1936,42 +1937,42 @@ A function taking an array of one type and a function argument, returning an arr A signature's parameter list consists of zero or more required parameters, followed by zero or more optional parameters, finally followed by an optional rest parameter. -  *ParameterList:* -   *RequiredParameterList* -   *OptionalParameterList* -   *RestParameter* -   *RequiredParameterList* `,` *OptionalParameterList* -   *RequiredParameterList* `,` *RestParameter* -   *OptionalParameterList* `,` *RestParameter* +  *ParameterList:* +   *RequiredParameterList* +   *OptionalParameterList* +   *RestParameter* +   *RequiredParameterList* `,` *OptionalParameterList* +   *RequiredParameterList* `,` *RestParameter* +   *OptionalParameterList* `,` *RestParameter*    *RequiredParameterList* `,` *OptionalParameterList* `,` *RestParameter* -  *RequiredParameterList:* -   *RequiredParameter* +  *RequiredParameterList:* +   *RequiredParameter*    *RequiredParameterList* `,` *RequiredParameter* -  *RequiredParameter:* -   *AccessibilityModifieropt* *BindingIdentifierOrPattern* *TypeAnnotationopt* +  *RequiredParameter:* +   *AccessibilityModifieropt* *BindingIdentifierOrPattern* *TypeAnnotationopt*    *BindingIdentifier* `:` *StringLiteral* -  *AccessibilityModifier:* -   `public` -   `private` +  *AccessibilityModifier:* +   `public` +   `private`    `protected` -  *BindingIdentifierOrPattern:* -   *BindingIdentifier* +  *BindingIdentifierOrPattern:* +   *BindingIdentifier*    *BindingPattern* -  *OptionalParameterList:* -   *OptionalParameter* +  *OptionalParameterList:* +   *OptionalParameter*    *OptionalParameterList* `,` *OptionalParameter* -  *OptionalParameter:* -   *AccessibilityModifieropt* *BindingIdentifierOrPattern* `?` *TypeAnnotationopt* -   *AccessibilityModifieropt* *BindingIdentifierOrPattern* *TypeAnnotationopt* *Initializer* +  *OptionalParameter:* +   *AccessibilityModifieropt* *BindingIdentifierOrPattern* `?` *TypeAnnotationopt* +   *AccessibilityModifieropt* *BindingIdentifierOrPattern* *TypeAnnotationopt* *Initializer*    *BindingIdentifier* `?` `:` *StringLiteral* -  *RestParameter:* +  *RestParameter:*    `...` *BindingIdentifier* *TypeAnnotationopt* A parameter declaration may specify either an identifier or a binding pattern ([5.2.2](#5.2.2)). The identifiers specified in parameter declarations and binding patterns in a parameter list must be unique within that parameter list. @@ -2009,11 +2010,11 @@ When a call signature with no return type annotation occurs in a context that ha When a parameter type annotation specifies a string literal type (section [3.2.9](#3.2.9)), the containing signature is considered a specialized signature. Specialized signatures are used to express patterns where specific string values for some parameters cause the types of other parameters or the function result to become further specialized. For example, the declaration ```TypeScript -interface Document { - createElement(tagName: "div"): HTMLDivElement; - createElement(tagName: "span"): HTMLSpanElement; - createElement(tagName: "canvas"): HTMLCanvasElement; - createElement(tagName: string): HTMLElement; +interface Document { + createElement(tagName: "div"): HTMLDivElement; + createElement(tagName: "span"): HTMLSpanElement; + createElement(tagName: "canvas"): HTMLCanvasElement; + createElement(tagName: string): HTMLElement; } ``` @@ -2027,7 +2028,7 @@ Every specialized call or construct signature in an object type must be assignab A construct signature defines the parameter list and return type associated with applying the `new` operator (section [4.14](#4.14)) to an instance of the containing type. A type may overload `new` operations by defining multiple construct signatures with different parameter lists. -  *ConstructSignature:* +  *ConstructSignature:*    `new` *TypeParametersopt* `(` *ParameterListopt* `)` *TypeAnnotationopt* The type parameters, parameter list, and return type of a construct signature are subject to the same rules as a call signature. @@ -2038,8 +2039,8 @@ A type containing construct signatures is said to be a ***constructor type***. An index signature defines a type constraint for properties in the containing type. -  *IndexSignature:* -   `[` *BindingIdentifier* `:` `string` `]` *TypeAnnotation* +  *IndexSignature:* +   `[` *BindingIdentifier* `:` `string` `]` *TypeAnnotation*    `[` *BindingIdentifier* `:` `number` `]` *TypeAnnotation* There are two kinds of index signatures: @@ -2057,7 +2058,7 @@ Index signatures affect the determination of the type that results from applying A method signature is shorthand for declaring a property of a function type. -  *MethodSignature:* +  *MethodSignature:*    *PropertyName* `?`*opt* *CallSignature* If the *PropertyName* is a computed property name ([2.2.3](#2.2.3)), it must specify a well-known symbol. If the *PropertyName* is followed by a question mark, the property is optional. Otherwise, the property is required. Only object type literals and interfaces can declare optional properties. @@ -2077,41 +2078,41 @@ f : { < T1, T2, ... > ( p1, p2, ... ) : R } A literal type may ***overload*** a method by declaring multiple method signatures with the same name but differing parameter lists. Overloads must either all be required (question mark omitted) or all be optional (question mark included). A set of overloaded method signatures correspond to a declaration of a single property with a type composed from an equivalent set of call signatures. Specifically ```TypeScript -f < T1, T2, ... > ( p1, p2, ... ) : R ; -f < U1, U2, ... > ( q1, q2, ... ) : S ; +f < T1, T2, ... > ( p1, p2, ... ) : R ; +f < U1, U2, ... > ( q1, q2, ... ) : S ; ... ``` is equivalent to ```TypeScript -f : { - < T1, T2, ... > ( p1, p2, ... ) : R ; - < U1, U2, ... > ( q1, q2, ... ) : S ; - ... +f : { + < T1, T2, ... > ( p1, p2, ... ) : R ; + < U1, U2, ... > ( q1, q2, ... ) : S ; + ... } ; ``` In the following example of an object type ```TypeScript -{ - func1(x: number): number; // Method signature - func2: (x: number) => number; // Function type literal - func3: { (x: number): number }; // Object type literal +{ + func1(x: number): number; // Method signature + func2: (x: number) => number; // Function type literal + func3: { (x: number): number }; // Object type literal } ``` the properties 'func1', 'func2', and 'func3' are all of the same type, namely an object type with a single call signature taking a number and returning a number. Likewise, in the object type ```TypeScript -{ - func4(x: number): number; - func4(s: string): string; - func5: { - (x: number): number; - (s: string): string; - }; +{ + func4(x: number): number; + func4(s: string): string; + func5: { + (x: number): number; + (s: string): string; + }; } ``` @@ -2121,7 +2122,7 @@ the properties 'func4' and 'func5' are of the same type, namely an object type w A type alias declaration introduces a ***type alias*** in the containing declaration space. -  *TypeAliasDeclaration:* +  *TypeAliasDeclaration:*    `type` *BindingIdentifier* *TypeParametersopt* `=` *Type* `;` A type alias serves as an alias for the type specified in the type alias declaration. Unlike an interface declaration, which always introduces a named object type, a type alias declaration can introduce a name for any kind of type, including primitive, union, and intersection types. @@ -2146,31 +2147,31 @@ Given this definition, the complete set of types upon which a type depends is th Some examples of type alias declarations: ```TypeScript -type StringOrNumber = string | number; -type Text = string | { text: string }; -type NameLookup = Dictionary; -type ObjectStatics = typeof Object; -type Callback = (data: T) => void; -type Pair = [T, T]; -type Coordinates = Pair; +type StringOrNumber = string | number; +type Text = string | { text: string }; +type NameLookup = Dictionary; +type ObjectStatics = typeof Object; +type Callback = (data: T) => void; +type Pair = [T, T]; +type Coordinates = Pair; type Tree = T | { left: Tree, right: Tree }; ``` Interface types have many similarities to type aliases for object type literals, but since interface types offer more capabilities they are generally preferred to type aliases. For example, the interface type ```TypeScript -interface Point { - x: number; - y: number; +interface Point { + x: number; + y: number; } ``` could be written as the type alias ```TypeScript -type Point = { - x: number; - y: number; +type Point = { + x: number; + y: number; }; ``` @@ -2215,8 +2216,8 @@ In effect, a type's apparent members make it a subtype of the 'Object' or 'Funct Some examples: ```TypeScript -var o: Object = { x: 10, y: 20 }; // Ok -var f: Function = (x: number) => x * x; // Ok +var o: Object = { x: 10, y: 20 }; // Ok +var f: Function = (x: number) => x * x; // Ok var err: Object = { toString: 0 }; // Error ``` @@ -2254,7 +2255,7 @@ interface X { f(): string; } interface Y { f(): string; } -var a: C; +var a: C; var b: C; ``` @@ -2342,9 +2343,9 @@ The assignment compatibility rules imply that, when assigning values or passing ```TypeScript function foo(x: { id: number; name?: string; }) { } -foo({ id: 1234 }); // Ok -foo({ id: 1234, name: "hello" }); // Ok -foo({ id: 1234, name: false }); // Error, name of wrong type +foo({ id: 1234 }); // Ok +foo({ id: 1234, name: "hello" }); // Ok +foo({ id: 1234, name: false }); // Error, name of wrong type foo({ name: "hello" }); // Error, id required but missing ``` @@ -2372,16 +2373,16 @@ The type inferred for an object literal (as described in section [4.5](#4.5)) is Consider the following example: ```TypeScript -interface CompilerOptions { - strict?: boolean; - sourcePath?: string; - targetPath?: string; +interface CompilerOptions { + strict?: boolean; + sourcePath?: string; + targetPath?: string; } -var options: CompilerOptions = { - strict: true, - sourcepath: "./src", // Error, excess or misspelled property - targetpath: "./bin" // Error, excess or misspelled property +var options: CompilerOptions = { + strict: true, + sourcepath: "./src", // Error, excess or misspelled property + targetpath: "./bin" // Error, excess or misspelled property }; ``` @@ -2390,17 +2391,17 @@ The 'CompilerOptions' type contains only optional properties, so without the exc In cases where excess properties are expected, an index signature can be added to the target type as an indicator of intent: ```TypeScript -interface InputElement { - name: string; - visible?: boolean; - [x: string]: any; // Allow additional properties of any type +interface InputElement { + name: string; + visible?: boolean; + [x: string]: any; // Allow additional properties of any type } -var address: InputElement = { - name: "Address", - visible: true, - help: "Enter address here", // Allowed because of index signature - shortcut: "Alt-A" // Allowed because of index signature +var address: InputElement = { + name: "Address", + visible: true, + help: "Enter address here", // Allowed because of index signature + shortcut: "Alt-A" // Allowed because of index signature }; ``` @@ -2459,10 +2460,10 @@ When this same technique is used to compare generic type references, two type re In certain circumstances, generic types that directly or indirectly reference themselves in a recursive fashion can lead to infinite series of distinct instantiations. For example, in the type ```TypeScript -interface List { - data: T; - next: List; - owner: List>; +interface List { + data: T; + next: List; + owner: List>; } ``` @@ -2481,9 +2482,9 @@ infers the type of 'name' to be the String primitive type since that is the type The following example shows the results of widening types to produce inferred variable types. ```TypeScript -var a = null; // var a: any -var b = undefined; // var b: any -var c = { x: 0, y: null }; // var c: { x: number, y: any } +var a = null; // var a: any +var b = undefined; // var b: any +var c = { x: 0, y: null }; // var c: { x: number, y: any } var d = [ null, undefined ]; // var d: any[] ``` @@ -2547,18 +2548,18 @@ Literals are typed as follows: Object literals are extended to support type annotations in methods and get and set accessors. -  *PropertyDefinition:* *( Modified )* -   *IdentifierReference* -   *CoverInitializedName* -   *PropertyName* `:` *AssignmentExpression* -   *PropertyName* *CallSignature* `{` *FunctionBody* `}` -   *GetAccessor* +  *PropertyDefinition:* *( Modified )* +   *IdentifierReference* +   *CoverInitializedName* +   *PropertyName* `:` *AssignmentExpression* +   *PropertyName* *CallSignature* `{` *FunctionBody* `}` +   *GetAccessor*    *SetAccessor* -  *GetAccessor:* +  *GetAccessor:*    `get` *PropertyName* `(` `)` *TypeAnnotationopt* `{` *FunctionBody* `}` -  *SetAccessor:* +  *SetAccessor:*    `set` *PropertyName* `(` *BindingIdentifierOrPattern* *TypeAnnotationopt* `)` `{` *FunctionBody* `}` The type of an object literal is an object type with the set of properties specified by the property assignments in the object literal. A get and set accessor may specify the same property name, but otherwise it is an error to specify multiple property assignments for the same property. @@ -2644,22 +2645,22 @@ A spread element must specify an expression of an array-like type (section [3.3. The rules above mean that an array literal is always of an array type, unless it is contextually typed by a tuple-like type. For example ```TypeScript -var a = [1, 2]; // number[] -var b = ["hello", true]; // (string | boolean)[] +var a = [1, 2]; // number[] +var b = ["hello", true]; // (string | boolean)[] var c: [number, string] = [3, "three"]; // [number, string] ``` When the output target is ECMAScript 3 or 5, array literals containing spread elements are rewritten to invocations of the `concat` method. For example, the assignments ```TypeScript -var a = [2, 3, 4]; +var a = [2, 3, 4]; var b = [0, 1, ...a, 5, 6]; ``` are rewritten to ```TypeScript -var a = [2, 3, 4]; +var a = [2, 3, 4]; var b = [0, 1].concat(a, [5, 6]); ``` @@ -2710,7 +2711,7 @@ The JavaScript code generated for a super property access is specified in sectio Function expressions are extended from JavaScript to optionally include parameter and return type annotations. -  *FunctionExpression:* *( Modified )* +  *FunctionExpression:* *( Modified )*    `function` *BindingIdentifieropt* *CallSignature* `{` *FunctionBody* `}` The descriptions of function declarations provided in chapter [6](#6) apply to function expressions as well, except that function expressions do not support overloading. @@ -2730,8 +2731,8 @@ A contextual signature *S* is extracted from a function type *T* as follows: In the example ```TypeScript -var f: (s: string) => string = function (s) { - return s.toLowerCase(); +var f: (s: string) => string = function (s) { + return s.toLowerCase(); }; ``` @@ -2741,7 +2742,7 @@ the function expression is contextually typed by the type of 'f', and since the Arrow functions are extended from JavaScript to optionally include parameter and return type annotations. -  *ArrowFormalParameters:* *( Modified )* +  *ArrowFormalParameters:* *( Modified )*    *CallSignature* The descriptions of function declarations provided in chapter [6](#6) apply to arrow functions as well, except that arrow functions do not support overloading. @@ -2765,23 +2766,23 @@ is exactly equivalent to Furthermore, arrow function expressions of the forms ```TypeScript -id => { ... } +id => { ... } id => expr ``` are exactly equivalent to ```TypeScript -( id ) => { ... } +( id ) => { ... } ( id ) => expr ``` Thus, the following examples are all equivalent: ```TypeScript -(x) => { return Math.sin(x); } -(x) => Math.sin(x) -x => { return Math.sin(x); } +(x) => { return Math.sin(x); } +(x) => Math.sin(x) +x => { return Math.sin(x); } x => Math.sin(x) ``` @@ -2790,29 +2791,29 @@ A function expression introduces a new dynamically bound `this`, whereas an arro In the example ```TypeScript -class Messenger { - message = "Hello World"; - start() { - setTimeout(() => alert(this.message), 3000); - } +class Messenger { + message = "Hello World"; + start() { + setTimeout(() => alert(this.message), 3000); + } }; -var messenger = new Messenger(); +var messenger = new Messenger(); messenger.start(); ``` the use of an arrow function expression causes the callback to have the same `this` as the surrounding 'start' method. Writing the callback as a standard function expression it becomes necessary to manually arrange access to the surrounding `this`, for example by copying it into a local variable: ```TypeScript -class Messenger { - message = "Hello World"; - start() { - var _this = this; - setTimeout(function() { alert(_this.message); }, 3000); - } +class Messenger { + message = "Hello World"; + start() { + var _this = this; + setTimeout(function() { alert(_this.message); }, 3000); + } }; -var messenger = new Messenger(); +var messenger = new Messenger(); messenger.start(); ``` @@ -2869,20 +2870,20 @@ where *object* and *index* are expressions, is used to access the property with The rules above mean that properties are strongly typed when accessed using bracket notation with the literal representation of their name. For example: ```TypeScript -var type = { - name: "boolean", - primitive: true +var type = { + name: "boolean", + primitive: true }; -var s = type["name"]; // string +var s = type["name"]; // string var b = type["primitive"]; // boolean ``` Tuple types assign numeric names to each of their elements and elements are therefore strongly typed when accessed using bracket notation with a numeric literal: ```TypeScript -var data: [string, number] = ["five", 5]; -var s = data[0]; // string +var data: [string, number] = ["five", 5]; +var s = data[0]; // string var n = data[1]; // number ``` @@ -2891,8 +2892,8 @@ var n = data[1]; // number A `new` operation has one of the following forms: ```TypeScript -new C -new C ( ... ) +new C +new C ( ... ) new C < ... > ( ... ) ``` @@ -2906,13 +2907,13 @@ where *C* is an expression. The first form is equivalent to supplying an empty a Function calls are extended from JavaScript to support optional type arguments. -  *Arguments:* *( Modified )* +  *Arguments:* *( Modified )*    *TypeArgumentsopt* `(` *ArgumentListopt* `)` A function call takes one of the forms ```TypeScript -func ( ... ) +func ( ... ) func < ... > ( ... ) ``` @@ -2979,11 +2980,11 @@ The process of inferentially typing an expression *e* by a type *T* is the same An example: ```TypeScript -function choose(x: T, y: T): T { - return Math.random() < 0.5 ? x : y; +function choose(x: T, y: T): T { + return Math.random() < 0.5 ? x : y; } -var x = choose(10, 20); // Ok, x of type number +var x = choose(10, 20); // Ok, x of type number var y = choose("Five", 5); // Error ``` @@ -2998,13 +2999,13 @@ In the second call to 'choose', an inference is made from type 'string' to 'T' f In the example ```TypeScript -function map(a: T[], f: (x: T) => U): U[] { - var result: U[] = []; - for (var i = 0; i < a.length; i++) result.push(f(a[i])); - return result; +function map(a: T[], f: (x: T) => U): U[] { + var result: U[] = []; + for (var i = 0; i < a.length; i++) result.push(f(a[i])); + return result; } -var names = ["Peter", "Paul", "Mary"]; +var names = ["Peter", "Paul", "Mary"]; var lengths = map(names, s => s.length); ``` @@ -3019,22 +3020,22 @@ and the resulting type of 'lengths' is therefore 'number[]'. In the example ```TypeScript -function zip(x: S[], y: T[], combine: (x: S) => (y: T) => U): U[] { - var len = Math.max(x.length, y.length); - var result: U[] = []; - for (var i = 0; i < len; i++) result.push(combine(x[i])(y[i])); - return result; +function zip(x: S[], y: T[], combine: (x: S) => (y: T) => U): U[] { + var len = Math.max(x.length, y.length); + var result: U[] = []; + for (var i = 0; i < len; i++) result.push(combine(x[i])(y[i])); + return result; } -var names = ["Peter", "Paul", "Mary"]; -var ages = [7, 9, 12]; +var names = ["Peter", "Paul", "Mary"]; +var ages = [7, 9, 12]; var pairs = zip(names, ages, s => n => ({ name: s, age: n })); ``` inferences for 'S', 'T' and 'U' in the call to 'zip' are made as follows: Using the first two parameters, inferences of 'string' for 'S' and 'number' for 'T' are made. For the third parameter, inferential typing of the outer arrow expression causes 'S' to become fixed such that the inferred type 'string' can be used for the parameter 's'. When a function expression is inferentially typed, its return expression(s) are also inferentially typed. Thus, the inner arrow function is inferentially typed, causing 'T' to become fixed such that the inferred type 'number' can be used for the parameter 'n'. The return type of the inner arrow function can then be determined, which in turn determines the return type of the function returned from the outer arrow function, and inferences are made from the type '(s: string) => (n: number) => { name: string; age: number }' to the type '(x: S) => (y: T) => R', inferring '{ name: string; age: number }' for 'R'. Thus the call to 'zip' is equivalent to ```TypeScript -var pairs = zip( +var pairs = zip( names, ages, s => n => ({ name: s, age: n })); ``` @@ -3055,7 +3056,7 @@ The grammar ambiguity is resolved as follows: In a context where one possible in This rule means that the call to 'f' above is interpreted as a call with one argument, which is a call to a generic function 'g' with two type arguments and one regular argument. However, the statements ```TypeScript -f(g < A, B > 7); +f(g < A, B > 7); f(g < A, B > +(7)); ``` @@ -3065,8 +3066,8 @@ are both interpreted as calls to 'f' with two arguments. TypeScript extends the JavaScript expression grammar with the ability to assert a type for an expression: -  *UnaryExpression:* *( Modified )* -   … +  *UnaryExpression:* *( Modified )* +   …    `<` *Type* `>` *UnaryExpression* A type assertion expression consists of a type enclosed in `<` and `>` followed by a unary expression. Type assertion expressions are purely a compile-time construct. Type assertions are *not* checked at run-time and have no impact on the emitted JavaScript (and therefore no run-time cost). The type and the enclosing `<` and `>` are simply removed from the generated code. @@ -3080,9 +3081,9 @@ class Shape { ... } class Circle extends Shape { ... } -function createShape(kind: string): Shape { - if (kind === "circle") return new Circle(); - ... +function createShape(kind: string): Shape { + if (kind === "circle") return new Circle(); + ... } var circle = createShape("circle"); @@ -3093,10 +3094,10 @@ the type annotations indicate that the 'createShape' function *might* return a ' As mentioned above, type assertions are not checked at run-time and it is up to the programmer to guard against errors, for example using the `instanceof` operator: ```TypeScript -var shape = createShape(shapeKind); -if (shape instanceof Circle) { - var circle = shape; - ... +var shape = createShape(shapeKind); +if (shape instanceof Circle) { + var circle = shape; + ... } ``` @@ -3155,8 +3156,8 @@ The 'void' operator takes an operand of any type and produces the value 'undefin The 'typeof' operator takes an operand of any type and produces a value of the String primitive type. In positions where a type is expected, 'typeof' can also be used in a type query (section [3.8.10](#3.8.10)) to produce the type of an expression. ```TypeScript -var x = 5; -var y = typeof x; // Use in an expression +var x = 5; +var y = typeof x; // Use in an expression var z: typeof x; // Use in a type query ``` @@ -3240,7 +3241,7 @@ The && operator permits the operands to be of any type and produces a result of The || operator permits the operands to be of any type. -If the || expression is contextually typed (section [4.23](#4.23)), the operands are contextually typed by the same type. Otherwise, the left operand is not contextually typed and the right operand is contextually typed by the type of the left operand. +If the || expression is contextually typed (section [4.23](#4.23)), the operands are contextually typed by the same type. Otherwise, the left operand is not contextually typed and the right operand is contextually typed by the type of the left operand. The type of the result is the union type of the two operand types. @@ -3301,7 +3302,7 @@ In a destructuring assignment expression, the type of the expression on the righ * *S* is the type Any, or * *S* has an apparent property with the property name specified in *P* of a type that is assignable to the target given in *P*, or * *P* specifies a numeric property name and *S* has a numeric index signature of a type that is assignable to the target given in *P*, or - * *S* has a string index signature of a type that is assignable to the target given in *P*. + * *S* has a string index signature of a type that is assignable to the target given in *P*. * *V* is an array assignment pattern, *S* is the type Any or an array-like type (section [3.3.2](#3.3.2)), and, for each assignment element *E* in *V*, * *S* is the type Any, or * *S* is a tuple-like type (section [3.3.3](#3.3.3)) with a property named *N* of a type that is assignable to the target given in *E*, where *N* is the numeric index of *E* in the array assignment pattern, or @@ -3314,17 +3315,17 @@ In an assignment property or element that includes a default value, the type of When the output target is ECMAScript 2015 or higher, destructuring variable assignments remain unchanged in the emitted JavaScript code. When the output target is ECMAScript 3 or 5, destructuring variable assignments are rewritten to series of simple assignments. For example, the destructuring assignment ```TypeScript -var x = 1; -var y = 2; +var x = 1; +var y = 2; [x, y] = [y, x]; ``` is rewritten to the simple variable assignments ```TypeScript -var x = 1; -var y = 2; -_a = [y, x], x = _a[0], y = _a[1]; +var x = 1; +var y = 2; +_a = [y, x], x = _a[0], y = _a[1]; var _a; ``` @@ -3348,13 +3349,13 @@ Type checking of an expression is improved in several contexts by factoring in t * In a contextually typed object literal, each property value expression is contextually typed by * the type of the property with a matching name in the contextual type, if any, or otherwise * for a numerically named property, the numeric index type of the contextual type, if any, or otherwise - * the string index type of the contextual type, if any. + * the string index type of the contextual type, if any. * In a contextually typed array literal expression containing no spread elements, an element expression at index *N* is contextually typed by * the type of the property with the numeric name *N* in the contextual type, if any, or otherwise * the numeric index type of the contextual type, if any. * In a contextually typed array literal expression containing one or more spread elements, an element expression at index *N* is contextually typed by the numeric index type of the contextual type, if any. * In a contextually typed parenthesized expression, the contained expression is contextually typed by the same type. -* In a type assertion, the expression is contextually typed by the indicated type. +* In a type assertion, the expression is contextually typed by the indicated type. * In a || operator expression, if the expression is contextually typed, the operands are contextually typed by the same type. Otherwise, the right expression is contextually typed by the type of the left expression. * In a contextually typed conditional operator expression, the operands are contextually typed by the same type. * In an assignment expression, the right hand expression is contextually typed by the type of the left hand expression. @@ -3362,22 +3363,22 @@ Type checking of an expression is improved in several contexts by factoring in t In the following example ```TypeScript -interface EventObject { - x: number; - y: number; +interface EventObject { + x: number; + y: number; } -interface EventHandlers { - mousedown?: (event: EventObject) => void; - mouseup?: (event: EventObject) => void; - mousemove?: (event: EventObject) => void; +interface EventHandlers { + mousedown?: (event: EventObject) => void; + mouseup?: (event: EventObject) => void; + mousemove?: (event: EventObject) => void; } function setEventHandlers(handlers: EventHandlers) { ... } -setEventHandlers({ - mousedown: e => { startTracking(e.x, e.y); }, - mouseup: e => { endTracking(); } +setEventHandlers({ + mousedown: e => { startTracking(e.x, e.y); }, + mouseup: e => { endTracking(); } }); ``` @@ -3388,13 +3389,13 @@ the object literal passed to 'setEventHandlers' is contextually typed to the 'Ev Type guards are particular expression patterns involving the 'typeof' and 'instanceof' operators that cause the types of variables or parameters to be ***narrowed*** to more specific types. For example, in the code below, knowledge of the static type of 'x' in combination with a 'typeof' check makes it safe to narrow the type of 'x' to string in the first branch of the 'if' statement and number in the second branch of the 'if' statement. ```TypeScript -function foo(x: number | string) { - if (typeof x === "string") { - return x.length; // x has type string here - } - else { - return x + 1; // x has type number here - } +function foo(x: number | string) { + if (typeof x === "string") { + return x.length; // x has type string here + } + else { + return x + 1; // x has type number here + } } ``` @@ -3441,8 +3442,8 @@ Note that type guards affect types of variables and parameters only and have no In the example ```TypeScript -function isLongString(obj: any) { - return typeof obj === "string" && obj.length > 100; +function isLongString(obj: any) { + return typeof obj === "string" && obj.length > 100; } ``` @@ -3451,9 +3452,9 @@ the `obj` parameter has type `string` in the right operand of the && operator. In the example ```TypeScript -function processValue(value: number | (() => number)) { - var x = typeof value !== "number" ? value() : value; - // Process number in x +function processValue(value: number | (() => number)) { + var x = typeof value !== "number" ? value() : value; + // Process number in x } ``` @@ -3462,13 +3463,13 @@ the value parameter has type `() => number` in the first conditional expression In the example ```TypeScript -function f(x: string | number | boolean) { - if (typeof x === "string" || typeof x === "number") { - var y = x; // Type of y is string | number - } - else { - var z = x; // Type of z is boolean - } +function f(x: string | number | boolean) { + if (typeof x === "string" || typeof x === "number") { + var y = x; // Type of y is string | number + } + else { + var z = x; // Type of z is boolean + } } ``` @@ -3477,12 +3478,12 @@ the type of x is `string | number | boolean` in the left operand of the || opera In the example ```TypeScript -class C { - data: string | string[]; - getData() { - var data = this.data; - return typeof data === "string" ? data : data.join(" "); - } +class C { + data: string | string[]; + getData() { + var data = this.data; + return typeof data === "string" ? data : data.join(" "); + } } ``` @@ -3491,12 +3492,12 @@ the type of the `data` variable is `string` in the first conditional expression In the example ```TypeScript -class NamedItem { - name: string; +class NamedItem { + name: string; } -function getName(obj: Object) { - return obj instanceof NamedItem ? obj.name : "unknown"; +function getName(obj: Object) { + return obj instanceof NamedItem ? obj.name : "unknown"; } ``` @@ -3512,10 +3513,10 @@ This chapter describes the static type checking TypeScript provides for JavaScri Blocks are extended to include local interface, type alias, and enum declarations (classes are already included by the ECMAScript 2015 grammar). -  *Declaration:* *( Modified )* -   … -   *InterfaceDeclaration* -   *TypeAliasDeclaration* +  *Declaration:* *( Modified )* +   … +   *InterfaceDeclaration* +   *TypeAliasDeclaration*    *EnumDeclaration* Local class, interface, type alias, and enum declarations are block scoped, similar to let and const declarations. @@ -3524,8 +3525,8 @@ Local class, interface, type alias, and enum declarations are block scoped, simi Variable statements are extended to include optional type annotations. -  *VariableDeclaration:* *( Modified )* -   *SimpleVariableDeclaration* +  *VariableDeclaration:* *( Modified )* +   *SimpleVariableDeclaration*    *DestructuringVariableDeclaration* A variable declaration is either a simple variable declaration or a destructuring variable declaration. @@ -3534,7 +3535,7 @@ A variable declaration is either a simple variable declaration or a destructurin A ***simple variable declaration*** introduces a single named variable and optionally assigns it an initial value. -  *SimpleVariableDeclaration:* +  *SimpleVariableDeclaration:*    *BindingIdentifier* *TypeAnnotationopt* *Initializeropt* The type *T* of a variable introduced by a simple variable declaration is determined as follows: @@ -3552,20 +3553,20 @@ When a variable declaration has a type annotation, it is an error for that type Below are some examples of simple variable declarations and their associated types. ```TypeScript -var a; // any -var b: number; // number -var c = 1; // number -var d = { x: 1, y: "hello" }; // { x: number; y: string; } +var a; // any +var b: number; // number +var c = 1; // number +var d = { x: 1, y: "hello" }; // { x: number; y: string; } var e: any = "test"; // any ``` The following is permitted because all declarations of the single variable 'x' associate the same type (Number) with 'x'. ```TypeScript -var x = 1; -var x: number; -if (x == 1) { - var x = 2; +var x = 1; +var x: number; +if (x == 1) { + var x = 2; } ``` @@ -3574,10 +3575,10 @@ In the following example, all five variables are of the same type, '{ x: number; ```TypeScript interface Point { x: number; y: number; } -var a = { x: 0, y: undefined }; -var b: Point = { x: 0, y: undefined }; -var c = { x: 0, y: undefined }; -var d: { x: number; y: number; } = { x: 0, y: undefined }; +var a = { x: 0, y: undefined }; +var b: Point = { x: 0, y: undefined }; +var c = { x: 0, y: undefined }; +var d: { x: number; y: number; } = { x: 0, y: undefined }; var e = <{ x: number; y: number; }> { x: 0, y: undefined }; ``` @@ -3585,7 +3586,7 @@ var e = <{ x: number; y: number; }> { x: 0, y: undefined }; A ***destructuring variable declaration*** introduces zero or more named variables and initializes them with values extracted from properties of an object or elements of an array. -  *DestructuringVariableDeclaration:* +  *DestructuringVariableDeclaration:*    *BindingPattern* *TypeAnnotationopt* *Initializer* Each binding property or element that specifies an identifier introduces a variable by that name. The type of the variable is the widened form (section [3.12](#3.12)) of the type associated with the binding property or element, as defined in the following. @@ -3640,10 +3641,10 @@ var { x, p: y, q: z = false } = getSomeObject(); is rewritten to the simple variable declarations ```TypeScript -var _a = getSomeObject(), - x = _a.x, - y = _a.p, - _b = _a.q, +var _a = getSomeObject(), + x = _a.x, + y = _a.p, + _b = _a.q, z = _b === void 0 ? false : _b; ``` @@ -3658,10 +3659,10 @@ var [x, y, z = 10] = getSomeArray(); is rewritten to the simple variable declarations ```TypeScript -var _a = getSomeArray(), - x = _a[0], - y = _a[1], - _b = _a[2], +var _a = getSomeArray(), + x = _a[0], + y = _a[1], + _b = _a[2], z = _b === void 0 ? 10 : _b; ``` @@ -3674,12 +3675,12 @@ var { x, p: [y, z = 10] = getSomeArray() } = getSomeObject(); is rewritten to ```TypeScript -var _a = getSomeObject(), - x = _a.x, - _b = _a.p, - _c = _b === void 0 ? getSomeArray() : _b, - y = _c[0], - _d = _c[1], +var _a = getSomeObject(), + x = _a.x, + _b = _a.p, + _c = _b === void 0 ? getSomeArray() : _b, + y = _c[0], + _d = _c[1], z = _d === void 0 ? 10 : _d; ``` @@ -3717,14 +3718,14 @@ the array literal initializer expression is contextually typed by the implied ty Let and const declarations are exended to include optional type annotations. -  *LexicalBinding:* *( Modified )* -   *SimpleLexicalBinding* +  *LexicalBinding:* *( Modified )* +   *SimpleLexicalBinding*    *DestructuringLexicalBinding* -  *SimpleLexicalBinding:* +  *SimpleLexicalBinding:*    *BindingIdentifier* *TypeAnnotationopt* *Initializeropt* -  *DestructuringLexicalBinding:* +  *DestructuringLexicalBinding:*    *BindingPattern* *TypeAnnotationopt* *Initializeropt* *TODO: Document scoping and types of [let and const declarations](https://github.com/Microsoft/TypeScript/pull/904)*. @@ -3780,8 +3781,8 @@ In a function implementation without a return type annotation, the return type i In the example ```TypeScript -function f(): (x: string) => number { - return s => s.length; +function f(): (x: string) => number { + return s => s.length; } ``` @@ -3813,8 +3814,8 @@ TypeScript extends JavaScript functions to include type parameters, parameter an Function declarations are extended to permit the function body to be omitted in overload declarations. -  *FunctionDeclaration:* *( Modified )* -   `function` *BindingIdentifieropt* *CallSignature* `{` *FunctionBody* `}` +  *FunctionDeclaration:* *( Modified )* +   `function` *BindingIdentifieropt* *CallSignature* `{` *FunctionBody* `}`    `function` *BindingIdentifieropt* *CallSignature* `;` A *FunctionDeclaration* introduces a named value of a function type in the containing declaration space. The *BindingIdentifier* is optional only when the function declaration occurs in an export default declaration (section [11.3.4.2](#11.3.4.2)). @@ -3836,26 +3837,26 @@ The parameter list of a function overload cannot specify default values for para The following is an example of a function with overloads. ```TypeScript -function attr(name: string): string; -function attr(name: string, value: string): Accessor; -function attr(map: any): Accessor; -function attr(nameOrMap: any, value?: string): any { - if (nameOrMap && typeof nameOrMap === "string") { - // handle string case - } - else { - // handle map case - } +function attr(name: string): string; +function attr(name: string, value: string): Accessor; +function attr(map: any): Accessor; +function attr(nameOrMap: any, value?: string): any { + if (nameOrMap && typeof nameOrMap === "string") { + // handle string case + } + else { + // handle map case + } } ``` Note that each overload and the final implementation specify the same identifier. The type of the local variable 'attr' introduced by this declaration is ```TypeScript -var attr: { - (name: string): string; - (name: string, value: string): Accessor; - (map: any): Accessor; +var attr: { + (name: string): string; + (name: string, value: string): Accessor; + (map: any): Accessor; }; ``` @@ -3873,13 +3874,13 @@ A function implementation without a return type annotation is said to be an ***i In the example ```TypeScript -function f(x: number) { - if (x <= 0) return x; - return g(x); +function f(x: number) { + if (x <= 0) return x; + return g(x); } -function g(x: number) { - return f(x - 1); +function g(x: number) { + return f(x - 1); } ``` @@ -3896,27 +3897,27 @@ Initializer expressions are evaluated in the scope of the function body but are When the output target is ECMAScript 3 or 5, for each parameter with an initializer, a statement that substitutes the default value for an omitted argument is included in the generated JavaScript, as described in section [6.6](#6.6). The example ```TypeScript -function strange(x: number, y = x * 2, z = x + y) { - return z; +function strange(x: number, y = x * 2, z = x + y) { + return z; } ``` generates JavaScript that is equivalent to ```TypeScript -function strange(x, y, z) { - if (y === void 0) { y = x * 2; } - if (z === void 0) { z = x + y; } - return z; +function strange(x, y, z) { + if (y === void 0) { y = x * 2; } + if (z === void 0) { z = x + y; } + return z; } ``` In the example ```TypeScript -var x = 1; -function f(a = x) { - var x = "hello"; +var x = 1; +function f(a = x) { + var x = "hello"; } ``` @@ -3940,8 +3941,8 @@ When the output target is ECMAScript 2015 or higher, except for removing the opt The example ```TypeScript -function drawText({ text = "", location: [x, y] = [0, 0], bold = false }) { - // Draw text +function drawText({ text = "", location: [x, y] = [0, 0], bold = false }) { + // Draw text } ``` @@ -3954,30 +3955,30 @@ declares a function `drawText` that takes a single parameter of the type When the output target is ECMAScript 3 or 5, the function is rewritten to ```TypeScript -function drawText(_a) { - var _b = _a.text, - text = _b === void 0 ? "" : _b, - _c = _a.location, - _d = _c === void 0 ? [0, 0] : _c, - x = _d[0], - y = _d[1], - _e = _a.bold, - bold = _e === void 0 ? false : _e; - // Draw text +function drawText(_a) { + var _b = _a.text, + text = _b === void 0 ? "" : _b, + _c = _a.location, + _d = _c === void 0 ? [0, 0] : _c, + x = _d[0], + y = _d[1], + _e = _a.bold, + bold = _e === void 0 ? false : _e; + // Draw text } ``` Destructuring parameter declarations do not permit type annotations on the individual binding patterns, as such annotations would conflict with the already established meaning of colons in object literals. Type annotations must instead be written on the top-level parameter declaration. For example ```TypeScript -interface DrawTextInfo { - text?: string; - location?: [number, number]; - bold?: boolean; +interface DrawTextInfo { + text?: string; + location?: [number, number]; + bold?: boolean; } -function drawText({ text, location: [x, y], bold }: DrawTextInfo) { - // Draw text +function drawText({ text, location: [x, y], bold }: DrawTextInfo) { + // Draw text } ``` @@ -3990,14 +3991,14 @@ Type parameters declared in the signature of a function implementation are in sc The following is an example of a generic function: ```TypeScript -interface Comparable { - localeCompare(other: any): number; +interface Comparable { + localeCompare(other: any): number; } -function compare(x: T, y: T): number { - if (x == null) return y == null ? 0 : -1; - if (y == null) return 1; - return x.localeCompare(y); +function compare(x: T, y: T): number { + if (x == null) return y == null ? 0 : -1; + if (y == null) return 1; + return x.localeCompare(y); } ``` @@ -4006,11 +4007,11 @@ Note that the 'x' and 'y' parameters are known to be subtypes of the constraint The type arguments of a call to a generic function may be explicitly specified in a call operation or may, when possible, be inferred (section [4.15.2](#4.15.2)) from the types of the regular arguments in the call. In the example ```TypeScript -class Person { - name: string; - localeCompare(other: Person) { - return compare(this.name, other.name); - } +class Person { + name: string; + localeCompare(other: Person) { + return compare(this.name, other.name); + } } ``` @@ -4021,9 +4022,9 @@ the type argument to 'compare' is automatically inferred to be the String type b A function declaration generates JavaScript code that is equivalent to: ```TypeScript -function () { - - +function () { + + } ``` @@ -4069,17 +4070,17 @@ Class declarations may reference interfaces in their implements clause to valida An interface declaration declares an ***interface type***. -  *InterfaceDeclaration:* +  *InterfaceDeclaration:*    `interface` *BindingIdentifier* *TypeParametersopt* *InterfaceExtendsClauseopt* *ObjectType* -  *InterfaceExtendsClause:* +  *InterfaceExtendsClause:*    `extends` *ClassOrInterfaceTypeList* -  *ClassOrInterfaceTypeList:* -   *ClassOrInterfaceType* +  *ClassOrInterfaceTypeList:* +   *ClassOrInterfaceType*    *ClassOrInterfaceTypeList* `,` *ClassOrInterfaceType* -  *ClassOrInterfaceType:* +  *ClassOrInterfaceType:*    *TypeReference* An *InterfaceDeclaration* introduces a named type (section [3.7](#3.7)) in the containing declaration space. The *BindingIdentifier* of an interface declaration may not be one of the predefined type names (section [3.8.1](#3.8.1)). @@ -4107,22 +4108,22 @@ An interface is permitted to inherit identical members from multiple base types Below is an example of two interfaces that contain properties with the same name but different types: ```TypeScript -interface Mover { - move(): void; - getStatus(): { speed: number; }; +interface Mover { + move(): void; + getStatus(): { speed: number; }; } -interface Shaker { - shake(): void; - getStatus(): { frequency: number; }; +interface Shaker { + shake(): void; + getStatus(): { frequency: number; }; } ``` An interface that extends 'Mover' and 'Shaker' must declare a new 'getStatus' property as it would otherwise inherit two 'getStatus' properties with different types. The new 'getStatus' property must be declared such that the resulting 'MoverShaker' is a subtype of both 'Mover' and 'Shaker': ```TypeScript -interface MoverShaker extends Mover, Shaker { - getStatus(): { speed: number; frequency: number; }; +interface MoverShaker extends Mover, Shaker { + getStatus(): { speed: number; frequency: number; }; } ``` @@ -4145,30 +4146,30 @@ In an interface with multiple declarations, the `extends` clauses are merged int For example, a sequence of declarations in this order: ```TypeScript -interface Document { - createElement(tagName: any): Element; +interface Document { + createElement(tagName: any): Element; } -interface Document { - createElement(tagName: string): HTMLElement; +interface Document { + createElement(tagName: string): HTMLElement; } -interface Document { - createElement(tagName: "div"): HTMLDivElement; - createElement(tagName: "span"): HTMLSpanElement; - createElement(tagName: "canvas"): HTMLCanvasElement; +interface Document { + createElement(tagName: "div"): HTMLDivElement; + createElement(tagName: "span"): HTMLSpanElement; + createElement(tagName: "canvas"): HTMLCanvasElement; } ``` is equivalent to the following single declaration: ```TypeScript -interface Document { - createElement(tagName: "div"): HTMLDivElement; - createElement(tagName: "span"): HTMLSpanElement; - createElement(tagName: "canvas"): HTMLCanvasElement; - createElement(tagName: string): HTMLElement; - createElement(tagName: any): Element; +interface Document { + createElement(tagName: "div"): HTMLDivElement; + createElement(tagName: "span"): HTMLSpanElement; + createElement(tagName: "canvas"): HTMLCanvasElement; + createElement(tagName: string): HTMLElement; + createElement(tagName: any): Element; } ``` @@ -4181,27 +4182,27 @@ Note that the members of the last interface declaration appear first in the merg When an interface type extends a class type it inherits the members of the class but not their implementations. It is as if the interface had declared all of the members of the class without providing an implementation. Interfaces inherit even the private and protected members of a base class. When a class containing private or protected members is the base type of an interface type, that interface type can only be implemented by that class or a descendant class. For example: ```TypeScript -class Control { - private state: any; +class Control { + private state: any; } -interface SelectableControl extends Control { - select(): void; +interface SelectableControl extends Control { + select(): void; } -class Button extends Control { - select() { } +class Button extends Control { + select() { } } -class TextBox extends Control { - select() { } +class TextBox extends Control { + select() { } } -class Image extends Control { +class Image extends Control { } -class Location { - select() { } +class Location { + select() { } } ``` @@ -4214,18 +4215,18 @@ Within the 'Control' class it is possible to access the 'state' private member t TypeScript does not provide a direct mechanism for dynamically testing whether an object implements a particular interface. Instead, TypeScript code can use the JavaScript technique of checking whether an appropriate set of members are present on the object. For example, given the declarations in section [7.1](#7.1), the following is a dynamic check for the 'MoverShaker' interface: ```TypeScript -var obj: any = getSomeObject(); -if (obj && obj.move && obj.shake && obj.getStatus) { - var moverShaker = obj; - ... +var obj: any = getSomeObject(); +if (obj && obj.move && obj.shake && obj.getStatus) { + var moverShaker = obj; + ... } ``` If such a check is used often it can be abstracted into a function: ```TypeScript -function asMoverShaker(obj: any): MoverShaker { - return obj && obj.move && obj.shake && obj.getStatus ? obj : null; +function asMoverShaker(obj: any): MoverShaker { + return obj && obj.move && obj.shake && obj.getStatus ? obj : null; } ``` @@ -4241,7 +4242,7 @@ TypeScript extends JavaScript classes to include type parameters, implements cla A class declaration declares a ***class type*** and a ***constructor function***. -  *ClassDeclaration:* *( Modified )* +  *ClassDeclaration:* *( Modified )*    `class` *BindingIdentifieropt* *TypeParametersopt* *ClassHeritage* `{` *ClassBody* `}` A *ClassDeclaration* introduces a named type (the class type) and a named value (the constructor function) in the containing declaration space. The class type is formed from the instance members declared in the class body and the instance members inherited from the base class. The constructor function is given an anonymous type formed from the constructor declaration, the static member declarations in the class body, and the static members inherited from the base class. The constructor function initializes and returns an instance of the class type. @@ -4253,29 +4254,29 @@ A class may optionally have type parameters (section [3.6.1](#3.6.1)) that serve The following example introduces both a named type called 'Point' (the class type) and a named value called 'Point' (the constructor function) in the containing declaration space. ```TypeScript -class Point { - constructor(public x: number, public y: number) { } - public length() { return Math.sqrt(this.x * this.x + this.y * this.y); } - static origin = new Point(0, 0); +class Point { + constructor(public x: number, public y: number) { } + public length() { return Math.sqrt(this.x * this.x + this.y * this.y); } + static origin = new Point(0, 0); } ``` The named type 'Point' is exactly equivalent to ```TypeScript -interface Point { - x: number; - y: number; - length(): number; +interface Point { + x: number; + y: number; + length(): number; } ``` The named value 'Point' is a constructor function whose type corresponds to the declaration ```TypeScript -var Point: { - new(x: number, y: number): Point; - origin: Point; +var Point: { + new(x: number, y: number): Point; + origin: Point; }; ``` @@ -4293,16 +4294,16 @@ the identifier 'Point' in the type annotation refers to the class type, whereas The heritage specification of a class consists of optional `extends` and `implements` clauses. The `extends` clause specifies the base class of the class and the `implements` clause specifies a set of interfaces for which to validate the class provides an implementation. -  *ClassHeritage:* *( Modified )* +  *ClassHeritage:* *( Modified )*    *ClassExtendsClauseopt* *ImplementsClauseopt* -  *ClassExtendsClause:* +  *ClassExtendsClause:*    `extends`  *ClassType* -  *ClassType:* +  *ClassType:*    *TypeReference* -  *ImplementsClause:* +  *ImplementsClause:*    `implements` *ClassOrInterfaceTypeList* A class that includes an `extends` clause is called a ***derived class***, and the class specified in the `extends` clause is called the ***base class*** of the derived class. When a class heritage specification omits the `extends` clause, the class does not have a base class. However, as is the case with every object type, type references (section [3.3.1](#3.3.1)) to the class will appear to have the members of the global interface type named 'Object' unless those members are hidden by members with the same name in the class. @@ -4319,9 +4320,9 @@ The following example illustrates a situation in which the first rule above woul ```TypeScript class A { a: number; } -namespace Foo { - var A = 1; - class B extends A { b: string; } +namespace Foo { + var A = 1; + class B extends A { b: string; } } ``` @@ -4335,9 +4336,9 @@ Note that because TypeScript has a structural type system, a class doesn't need The class body consists of zero or more constructor or member declarations. Statements are not allowed in the body of a class—they must be placed in the constructor or in members. -  *ClassElement:* *( Modified )* -   *ConstructorDeclaration* -   *PropertyMemberDeclaration* +  *ClassElement:* *( Modified )* +   *ConstructorDeclaration* +   *PropertyMemberDeclaration*    *IndexMemberDeclaration* The body of class may optionally contain a single constructor declaration. Constructor declarations are described in section [8.3](#8.3). @@ -4373,24 +4374,24 @@ Private and protected accessibility is enforced only at compile-time and serves The following example demonstrates private and protected accessibility: ```TypeScript -class A { - private x: number; - protected y: number; - static f(a: A, b: B) { - a.x = 1; // Ok - b.x = 1; // Ok - a.y = 1; // Ok - b.y = 1; // Ok - } +class A { + private x: number; + protected y: number; + static f(a: A, b: B) { + a.x = 1; // Ok + b.x = 1; // Ok + a.y = 1; // Ok + b.y = 1; // Ok + } } -class B extends A { - static f(a: A, b: B) { - a.x = 1; // Error, x only accessible within A - b.x = 1; // Error, x only accessible within A - a.y = 1; // Error, y must be accessed through instance of B - b.y = 1; // Ok - } +class B extends A { + static f(a: A, b: B) { + a.x = 1; // Error, x only accessible within A + b.x = 1; // Error, x only accessible within A + a.y = 1; // Error, y must be accessed through instance of B + b.y = 1; // Ok + } } ``` @@ -4426,37 +4427,37 @@ All instance property members (including those that are private or protected) of In the example ```TypeScript -class A { - public x: number; - public f() { } - public g(a: any) { return undefined; } - static s: string; +class A { + public x: number; + public f() { } + public g(a: any) { return undefined; } + static s: string; } -class B extends A { - public y: number; - public g(b: boolean) { return false; } +class B extends A { + public y: number; + public g(b: boolean) { return false; } } ``` the class type of 'A' is equivalent to ```TypeScript -interface A { - x: number; - f: () => void; - g: (a: any) => any; +interface A { + x: number; + f: () => void; + g: (a: any) => any; } ``` and the class type of 'B' is equivalent to ```TypeScript -interface B { - x: number; - y: number; - f: () => void; - g: (b: boolean) => boolean; +interface B { + x: number; + y: number; + f: () => void; + g: (b: boolean) => boolean; } ``` @@ -4481,8 +4482,8 @@ Every class automatically contains a static property member named 'prototype', t The example ```TypeScript -class Pair { - constructor(public item1: T1, public item2: T2) { } +class Pair { + constructor(public item1: T1, public item2: T2) { } } class TwoArrays extends Pair { } @@ -4491,26 +4492,26 @@ class TwoArrays extends Pair { } introduces two named types corresponding to ```TypeScript -interface Pair { - item1: T1; - item2: T2; +interface Pair { + item1: T1; + item2: T2; } -interface TwoArrays { - item1: T[]; - item2: T[]; +interface TwoArrays { + item1: T[]; + item2: T[]; } ``` and two constructor functions corresponding to ```TypeScript -var Pair: { - new (item1: T1, item2: T2): Pair; +var Pair: { + new (item1: T1, item2: T2): Pair; } -var TwoArrays: { - new (item1: T[], item2: T[]): TwoArrays; +var TwoArrays: { + new (item1: T[], item2: T[]): TwoArrays; } ``` @@ -4520,8 +4521,8 @@ Note that each construct signature in the constructor function types has the sam A constructor declaration declares the constructor function of a class. -  *ConstructorDeclaration:* -   *AccessibilityModifieropt* `constructor` `(` *ParameterListopt* `)` `{` *FunctionBody* `}` +  *ConstructorDeclaration:* +   *AccessibilityModifieropt* `constructor` `(` *ParameterListopt* `)` `{` *FunctionBody* `}`    *AccessibilityModifieropt* `constructor` `(` *ParameterListopt* `)` `;` Constructor declarations that specify a body are called ***constructor implementations*** and constructor declarations without a body are called ***constructor overloads***. It is possible to specify multiple constructor overloads in a class, but a class can have at most one constructor implementation. All constructor declarations in a class must specify the same set of modifiers. Only public constructors are supported and private or protected constructors result in an error. @@ -4543,24 +4544,24 @@ Similar to functions, only the constructor implementation (and not constructor o A parameter of a *ConstructorImplementation* may be prefixed with a `public`, `private`, or `protected` modifier. This is called a ***parameter property declaration*** and is shorthand for declaring a property with the same name as the parameter and initializing it with the value of the parameter. For example, the declaration ```TypeScript -class Point { - constructor(public x: number, public y: number) { - // Constructor body - } +class Point { + constructor(public x: number, public y: number) { + // Constructor body + } } ``` is equivalent to writing ```TypeScript -class Point { - public x: number; - public y: number; - constructor(x: number, y: number) { - this.x = x; - this.y = y; - // Constructor body - } +class Point { + public x: number; + public y: number; + constructor(x: number, y: number) { + this.x = x; + this.y = y; + // Constructor body + } } ``` @@ -4571,10 +4572,10 @@ A parameter property declaration may declare an optional parameter (by including Super calls (section [4.9.1](#4.9.1)) are used to call the constructor of the base class. A super call consists of the keyword `super` followed by an argument list enclosed in parentheses. For example: ```TypeScript -class ColoredPoint extends Point { - constructor(x: number, y: number, public color: string) { - super(x, y); - } +class ColoredPoint extends Point { + constructor(x: number, y: number, public color: string) { + super(x, y); + } } ``` @@ -4607,9 +4608,9 @@ and then executes the instance member variable initializers, if any. Property member declarations can be member variable declarations, member function declarations, or member accessor declarations. -  *PropertyMemberDeclaration:* -   *MemberVariableDeclaration* -   *MemberFunctionDeclaration* +  *PropertyMemberDeclaration:* +   *MemberVariableDeclaration* +   *MemberFunctionDeclaration*    *MemberAccessorDeclaration* Member declarations without a `static` modifier are called instance member declarations. Instance property member declarations declare properties in the class type (section [8.2.4](#8.2.4)), and must specify names that are unique among all instance property member and parameter property declarations in the containing class, with the exception that instance get and set accessor declarations may pairwise specify the same name. @@ -4625,35 +4626,35 @@ Every class automatically contains a static property member named 'prototype', t Below is an example of a class containing both instance and static property member declarations: ```TypeScript -class Point { - constructor(public x: number, public y: number) { } - public distance(p: Point) { - var dx = this.x - p.x; - var dy = this.y - p.y; - return Math.sqrt(dx * dx + dy * dy); - } - static origin = new Point(0, 0); - static distance(p1: Point, p2: Point) { return p1.distance(p2); } +class Point { + constructor(public x: number, public y: number) { } + public distance(p: Point) { + var dx = this.x - p.x; + var dy = this.y - p.y; + return Math.sqrt(dx * dx + dy * dy); + } + static origin = new Point(0, 0); + static distance(p1: Point, p2: Point) { return p1.distance(p2); } } ``` The class type 'Point' has the members: ```TypeScript -interface Point { - x: number; - y: number; - distance(p: Point); +interface Point { + x: number; + y: number; + distance(p: Point); } ``` and the constructor function 'Point' has a type corresponding to the declaration: ```TypeScript -var Point: { - new(x: number, y: number): Point; - origin: Point; - distance(p1: Point, p2: Point): number; +var Point: { + new(x: number, y: number): Point; + origin: Point; + distance(p1: Point, p2: Point): number; } ``` @@ -4661,7 +4662,7 @@ var Point: { A member variable declaration declares an instance member variable or a static member variable. -  *MemberVariableDeclaration:* +  *MemberVariableDeclaration:*    *AccessibilityModifieropt* `static`*opt* *PropertyName* *TypeAnnotationopt* *Initializeropt* `;` The type associated with a member variable declaration is determined in the same manner as an ordinary variable declaration (see section [5.2](#5.2)). @@ -4675,29 +4676,29 @@ Initializer expressions for instance member variables are evaluated in the scope Since instance member variable initializers are equivalent to assignments to properties of `this` in the constructor, the example ```TypeScript -class Employee { - public name: string; - public address: string; - public retired = false; - public manager: Employee = null; - public reports: Employee[] = []; +class Employee { + public name: string; + public address: string; + public retired = false; + public manager: Employee = null; + public reports: Employee[] = []; } ``` is equivalent to ```TypeScript -class Employee { - public name: string; - public address: string; - public retired: boolean; - public manager: Employee; - public reports: Employee[]; - constructor() { - this.retired = false; - this.manager = null; - this.reports = []; - } +class Employee { + public name: string; + public address: string; + public retired: boolean; + public manager: Employee; + public reports: Employee[]; + constructor() { + this.retired = false; + this.manager = null; + this.reports = []; + } } ``` @@ -4705,8 +4706,8 @@ class Employee { A member function declaration declares an instance member function or a static member function. -  *MemberFunctionDeclaration:* -   *AccessibilityModifieropt* `static`*opt* *PropertyName* *CallSignature* `{` *FunctionBody* `}` +  *MemberFunctionDeclaration:* +   *AccessibilityModifieropt* `static`*opt* *PropertyName* *CallSignature* `{` *FunctionBody* `}`    *AccessibilityModifieropt* `static`*opt* *PropertyName* *CallSignature* `;` A member function declaration is processed in the same manner as an ordinary function declaration (section [6](#6)), except that in a member function `this` has a known type. @@ -4720,48 +4721,48 @@ A static member function declaration declares a property in the constructor func A member function can access overridden base class members using a super property access (section [4.9.2](#4.9.2)). For example ```TypeScript -class Point { - constructor(public x: number, public y: number) { } - public toString() { - return "x=" + this.x + " y=" + this.y; - } +class Point { + constructor(public x: number, public y: number) { } + public toString() { + return "x=" + this.x + " y=" + this.y; + } } -class ColoredPoint extends Point { - constructor(x: number, y: number, public color: string) { - super(x, y); - } - public toString() { - return super.toString() + " color=" + this.color; - } +class ColoredPoint extends Point { + constructor(x: number, y: number, public color: string) { + super(x, y); + } + public toString() { + return super.toString() + " color=" + this.color; + } } ``` In a static member function, `this` represents the constructor function object on which the static member function was invoked. Thus, a call to 'new this()' may actually invoke a derived class constructor: ```TypeScript -class A { - a = 1; - static create() { - return new this(); - } +class A { + a = 1; + static create() { + return new this(); + } } -class B extends A { - b = 2; +class B extends A { + b = 2; } -var x = A.create(); // new A() +var x = A.create(); // new A() var y = B.create(); // new B() ``` Note that TypeScript doesn't require or verify that derived constructor functions are subtypes of base constructor functions. In other words, changing the declaration of 'B' to ```TypeScript -class B extends A { - constructor(public b: number) { - super(); - } +class B extends A { + constructor(public b: number) { + super(); + } } ``` @@ -4771,8 +4772,8 @@ does not cause errors in the example, even though the call to the constructor fr A member accessor declaration declares an instance member accessor or a static member accessor. -  *MemberAccessorDeclaration:* -   *AccessibilityModifieropt* `static`*opt* *GetAccessor* +  *MemberAccessorDeclaration:* +   *AccessibilityModifieropt* `static`*opt* *GetAccessor*    *AccessibilityModifieropt* `static`*opt* *SetAccessor* Get and set accessors are processed in the same manner as in an object literal (section [4.5](#4.5)), except that a contextual type is never available in a member accessor declaration. @@ -4797,7 +4798,7 @@ If the *PropertyName* of a property member declaration is a computed property na An index member declaration introduces an index signature (section [3.9.4](#3.9.4)) in the class type. -  *IndexMemberDeclaration:* +  *IndexMemberDeclaration:*    *IndexSignature* `;` Index member declarations have no body and cannot specify an accessibility modifier. @@ -4821,16 +4822,16 @@ When the output target is ECMAScript 2015 or higher, type parameters, implements A class with no `extends` clause generates JavaScript equivalent to the following: ```TypeScript -var = (function () { - function () { - - - - - } - - - return ; +var = (function () { + function () { + + + + + } + + + return ; })(); ``` @@ -4863,18 +4864,18 @@ where *MemberName* is the name of the member variable and *InitializerExpression An instance member function declaration generates a statement of the form ```TypeScript -.prototype. = function () { - - +.prototype. = function () { + + } ``` and static member function declaration generates a statement of the form ```TypeScript -. = function () { - - +. = function () { + + } ``` @@ -4883,30 +4884,30 @@ where *MemberName* is the name of the member function, and *FunctionParameters*, A get or set instance member accessor declaration, or a pair of get and set instance member accessor declarations with the same name, generates a statement of the form ```TypeScript -Object.defineProperty(.prototype, "", { - get: function () { - - }, - set: function () { - - }, - enumerable: true, - configurable: true +Object.defineProperty(.prototype, "", { + get: function () { + + }, + set: function () { + + }, + enumerable: true, + configurable: true }; ``` and a get or set static member accessor declaration, or a pair of get and set static member accessor declarations with the same name, generates a statement of the form ```TypeScript -Object.defineProperty(, "", { - get: function () { - - }, - set: function () { - - }, - enumerable: true, - configurable: true +Object.defineProperty(, "", { + get: function () { + + }, + set: function () { + + }, + enumerable: true, + configurable: true }; ``` @@ -4925,29 +4926,29 @@ where *MemberName* is the name of the static variable, and *InitializerExpressio A class with an `extends` clause generates JavaScript equivalent to the following: ```TypeScript -var = (function (_super) { - __extends(, _super); - function () { - - - - - - } - - - return ; +var = (function (_super) { + __extends(, _super); + function () { + + + + + + } + + + return ; })(); ``` In addition, the '__extends' function below is emitted at the beginning of the JavaScript source file. It copies all properties from the base constructor function object to the derived constructor function object (in order to inherit static members), and appropriately establishes the 'prototype' property of the derived constructor function object. ```TypeScript -var __extends = this.__extends || function(d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - function f() { this.constructor = d; } - f.prototype = b.prototype; - d.prototype = new f(); +var __extends = this.__extends || function(d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function f() { this.constructor = d; } + f.prototype = b.prototype; + d.prototype = new f(); } ``` @@ -5005,7 +5006,7 @@ An enum type is a distinct subtype of the Number primitive type with an associat An enum declaration declares an ***enum type*** and an ***enum object***. -  *EnumDeclaration:* +  *EnumDeclaration:*    `const`*opt* `enum` *BindingIdentifier* `{` *EnumBodyopt* `}` An *EnumDeclaration* introduces a named type (the enum type) and a named value (the enum object) in the containing declaration space. The enum type is a distinct subtype of the Number primitive type. The enum object is a value of an anonymous object type containing a set of properties, all of the enum type, corresponding to the values declared for the enum type in the body of the declaration. The enum object's type furthermore includes a numeric index signature with the signature '[x: number]: string'. @@ -5023,18 +5024,18 @@ enum Color { Red, Green, Blue } declares a subtype of the Number primitive type called 'Color' and introduces a variable 'Color' with a type that corresponds to the declaration ```TypeScript -var Color: { - [x: number]: string; - Red: Color; - Green: Color; - Blue: Color; +var Color: { + [x: number]: string; + Red: Color; + Green: Color; + Blue: Color; }; ``` The numeric index signature reflects a "reverse mapping" that is automatically generated in every enum object, as described in section [9.5](#9.5). The reverse mapping provides a convenient way to obtain the string representation of an enum value. For example ```TypeScript -var c = Color.Red; +var c = Color.Red; console.log(Color[c]); // Outputs "Red" ``` @@ -5042,18 +5043,18 @@ console.log(Color[c]); // Outputs "Red" The body of an enum declaration defines zero or more enum members which are the named values of the enum type. Each enum member has an associated numeric value of the primitive type introduced by the enum declaration. -  *EnumBody:* +  *EnumBody:*    *EnumMemberList* `,`*opt* -  *EnumMemberList:* -   *EnumMember* +  *EnumMemberList:* +   *EnumMember*    *EnumMemberList* `,` *EnumMember* -  *EnumMember:* -   *PropertyName* +  *EnumMember:* +   *PropertyName*    *PropertyName* = *EnumValue* -  *EnumValue:* +  *EnumValue:*    *AssignmentExpression* The *PropertyName* of an enum member cannot be a computed property name ([2.2.3](#2.2.3)). @@ -5079,12 +5080,12 @@ A ***constant enum expression*** is a subset of the expression grammar that can In the example ```TypeScript -enum Test { - A, - B, - C = Math.floor(Math.random() * 1000), - D = 10, - E +enum Test { + A, + B, + C = Math.floor(Math.random() * 1000), + D = 10, + E } ``` @@ -5093,13 +5094,13 @@ enum Test { In the example ```TypeScript -enum Style { - None = 0, - Bold = 1, - Italic = 2, - Underline = 4, - Emphasis = Bold | Italic, - Hyperlink = Bold | Underline +enum Style { + None = 0, + Bold = 1, + Italic = 2, + Underline = 4, + Emphasis = Bold | Italic, + Hyperlink = Bold | Underline } ``` @@ -5120,14 +5121,14 @@ An enum declaration that specifies a `const` modifier is a ***constant enum decl Unlike regular enum declarations, constant enum declarations are completely erased in the emitted JavaScript code. For this reason, it is an error to reference a constant enum object in any other context than a property access that selects one of the enum's members. For example: ```TypeScript -const enum Comparison { - LessThan = -1, - EqualTo = 0, - GreaterThan = 1 +const enum Comparison { + LessThan = -1, + EqualTo = 0, + GreaterThan = 1 } -var x = Comparison.EqualTo; // Ok, replaced with 0 in emitted code -var y = Comparison[Comparison.EqualTo]; // Error +var x = Comparison.EqualTo; // Ok, replaced with 0 in emitted code +var y = Comparison[Comparison.EqualTo]; // Error var z = Comparison; // Error ``` @@ -5138,9 +5139,9 @@ The entire const enum declaration is erased in the emitted JavaScript code. Thus An enum declaration generates JavaScript equivalent to the following: ```TypeScript -var ; -(function () { - +var ; +(function () { + })(||(={})); ``` @@ -5157,11 +5158,11 @@ where *MemberName* is the name of the enum member and *Value* is the assigned co For example, the 'Color' enum example from section [9.1](#9.1) generates the following JavaScript: ```TypeScript -var Color; -(function (Color) { - Color[Color["Red"] = 0] = "Red"; - Color[Color["Green"] = 1] = "Green"; - Color[Color["Blue"] = 2] = "Blue"; +var Color; +(function (Color) { + Color[Color["Red"] = 0] = "Red"; + Color[Color["Green"] = 1] = "Green"; + Color[Color["Blue"] = 2] = "Blue"; })(Color||(Color={})); ``` @@ -5175,11 +5176,11 @@ Namespaces provide a mechanism for organizing code and declarations in hierarchi A namespace declaration introduces a name with a namespace meaning and, in the case of an instantiated namespace, a value meaning in the containing declaration space. -  *NamespaceDeclaration:* +  *NamespaceDeclaration:*    `namespace` *IdentifierPath* `{` *NamespaceBody* `}` -  *IdentifierPath:* -   *BindingIdentifier* +  *IdentifierPath:* +   *BindingIdentifier*    *IdentifierPath* `.` *BindingIdentifier* Namespaces are declared using the `namespace` keyword, but for backward compatibility of earlier versions of TypeScript a `module` keyword can also be used. @@ -5189,15 +5190,15 @@ Namespaces are either ***instantiated*** or ***non-instantiated***. A non-instan When a namespace identifier is referenced as a *NamespaceName* (section [3.8.2](#3.8.2)) it denotes a container of namespace and type names, and when a namespace identifier is referenced as a *PrimaryExpression* (section [4.3](#4.3)) it denotes the singleton namespace instance. For example: ```TypeScript -namespace M { - export interface P { x: number; y: number; } - export var a = 1; +namespace M { + export interface P { x: number; y: number; } + export var a = 1; } -var p: M.P; // M used as NamespaceName -var m = M; // M used as PrimaryExpression -var x1 = M.a; // M used as PrimaryExpression -var x2 = m.a; // Same as M.a +var p: M.P; // M used as NamespaceName +var m = M; // M used as PrimaryExpression +var x1 = M.a; // M used as PrimaryExpression +var x2 = m.a; // Same as M.a var q: m.P; // Error ``` @@ -5208,30 +5209,30 @@ If the declaration of 'M' above had excluded the exported variable 'a', 'M' woul A namespace declaration that specifies an *IdentifierPath* with more than one identifier is equivalent to a series of nested single-identifier namespace declarations where all but the outermost are automatically exported. For example: ```TypeScript -namespace A.B.C { - export var x = 1; +namespace A.B.C { + export var x = 1; } ``` corresponds to ```TypeScript -namespace A { - export namespace B { - export namespace C { - export var x = 1; - } - } +namespace A { + export namespace B { + export namespace C { + export var x = 1; + } + } } ``` The hierarchy formed by namespace and named type names partially mirrors that formed by namespace instances and members. The example ```TypeScript -namespace A { - export namespace B { - export class C { } - } +namespace A { + export namespace B { + export class C { } + } } ``` @@ -5247,49 +5248,49 @@ the two occurrences of 'A.B.C' in fact refer to different entities. It is the co The body of a namespace corresponds to a function that is executed once to initialize the namespace instance. -  *NamespaceBody:* +  *NamespaceBody:*    *NamespaceElementsopt* -  *NamespaceElements:* -   *NamespaceElement* +  *NamespaceElements:* +   *NamespaceElement*    *NamespaceElements* *NamespaceElement* -  *NamespaceElement:* -   *Statement* -   *LexicalDeclaration* -   *FunctionDeclaration* -   *GeneratorDeclaration* -   *ClassDeclaration* -   *InterfaceDeclaration* -   *TypeAliasDeclaration* -   *EnumDeclaration* -   *NamespaceDeclaration -   AmbientDeclaration -   ImportAliasDeclaration +  *NamespaceElement:* +   *Statement* +   *LexicalDeclaration* +   *FunctionDeclaration* +   *GeneratorDeclaration* +   *ClassDeclaration* +   *InterfaceDeclaration* +   *TypeAliasDeclaration* +   *EnumDeclaration* +   *NamespaceDeclaration +   AmbientDeclaration +   ImportAliasDeclaration    ExportNamespaceElement* -  *ExportNamespaceElement:* -   `export` *VariableStatement* -   `export` *LexicalDeclaration* -   `export` *FunctionDeclaration* -   `export` *GeneratorDeclaration* -   `export` *ClassDeclaration* -   `export` *InterfaceDeclaration* -   `export` *TypeAliasDeclaration* -   `export` *EnumDeclaration* -   `export` *NamespaceDeclaration* -   `export` *AmbientDeclaration* +  *ExportNamespaceElement:* +   `export` *VariableStatement* +   `export` *LexicalDeclaration* +   `export` *FunctionDeclaration* +   `export` *GeneratorDeclaration* +   `export` *ClassDeclaration* +   `export` *InterfaceDeclaration* +   `export` *TypeAliasDeclaration* +   `export` *EnumDeclaration* +   `export` *NamespaceDeclaration* +   `export` *AmbientDeclaration*    `export` *ImportAliasDeclaration* ## 10.3 Import Alias Declarations Import alias declarations are used to create local aliases for entities in other namespaces. -  *ImportAliasDeclaration:* +  *ImportAliasDeclaration:*    `import` *BindingIdentifier* `=` *EntityName* `;` -  *EntityName:* -   *NamespaceName* +  *EntityName:* +   *NamespaceName*    *NamespaceName* `.` *IdentifierReference* An *EntityName* consisting of a single identifier is resolved as a *NamespaceName* and is thus required to reference a namespace. The resulting local alias references the given namespace and is itself classified as a namespace. @@ -5299,16 +5300,16 @@ An *EntityName* consisting of more than one identifier is resolved as a *Namespa In the example ```TypeScript -namespace A { - export interface X { s: string } - export var X: X; +namespace A { + export interface X { s: string } + export var X: X; } -namespace B { - interface A { n: number } - import Y = A; // Alias for namespace A - import Z = A.X; // Alias for type and value A.X - var v: Z = Z; +namespace B { + interface A { n: number } + import Y = A; // Alias for namespace A + import Z = A.X; // Alias for type and value A.X + var v: Z = Z; } ``` @@ -5317,13 +5318,13 @@ within 'B', 'Y' is an alias only for namespace 'A' and not the local interface ' If the *NamespaceName* portion of an *EntityName* references an instantiated namespace, the *NamespaceName* is required to reference the namespace instance when evaluated as an expression. In the example ```TypeScript -namespace A { - export interface X { s: string } +namespace A { + export interface X { s: string } } -namespace B { - var A = 1; - import Y = A; +namespace B { + var A = 1; + import Y = A; } ``` @@ -5359,10 +5360,10 @@ In the example ```TypeScript interface A { x: string; } -namespace M { - export interface B { x: A; } - export interface C { x: B; } - export function foo(c: C) { … } +namespace M { + export interface B { x: A; } + export interface C { x: B; } + export function foo(c: C) { … } } ``` @@ -5375,37 +5376,37 @@ Namespaces are "open-ended" and namespace declarations with the same qualified n File a.ts: ```TypeScript -namespace outer { - var local = 1; // Non-exported local variable - export var a = local; // outer.a - export namespace inner { - export var x = 10; // outer.inner.x - } +namespace outer { + var local = 1; // Non-exported local variable + export var a = local; // outer.a + export namespace inner { + export var x = 10; // outer.inner.x + } } ``` File b.ts: ```TypeScript -namespace outer { - var local = 2; // Non-exported local variable - export var b = local; // outer.b - export namespace inner { - export var y = 20; // outer.inner.y - } +namespace outer { + var local = 2; // Non-exported local variable + export var b = local; // outer.b + export namespace inner { + export var y = 20; // outer.inner.y + } } ``` Assuming the two source files are part of the same program, the two declarations will have the global namespace as their common root and will therefore contribute to the same namespace instance, the instance type of which will be: ```TypeScript -{ - a: number; - b: number; - inner: { - x: number; - y: number; - }; +{ + a: number; + b: number; + inner: { + x: number; + y: number; + }; } ``` @@ -5424,24 +5425,24 @@ When merging a non-ambient function or class declaration and a non-ambient names The example ```TypeScript -interface Point { - x: number; - y: number; +interface Point { + x: number; + y: number; } -function point(x: number, y: number): Point { - return { x: x, y: y }; +function point(x: number, y: number): Point { + return { x: x, y: y }; } -namespace point { - export var origin = point(0, 0); - export function equals(p1: Point, p2: Point) { - return p1.x == p2.x && p1.y == p2.y; - } +namespace point { + export var origin = point(0, 0); + export function equals(p1: Point, p2: Point) { + return p1.x == p2.x && p1.y == p2.y; + } } -var p1 = point(0, 0); -var p2 = point.origin; +var p1 = point(0, 0); +var p2 = point.origin; var b = point.equals(p1, p2); ``` @@ -5452,9 +5453,9 @@ declares 'point' as a function object with two properties, 'origin' and 'equals' A namespace generates JavaScript code that is equivalent to the following: ```TypeScript -var ; -(function() { - +var ; +(function() { + })(||(={})); ``` @@ -5494,16 +5495,16 @@ TypeScript implements support for ECMAScript 2015 modules and supports down-leve A TypeScript ***program*** consists of one or more source files. -  *SourceFile:* -   *ImplementationSourceFile* +  *SourceFile:* +   *ImplementationSourceFile*    *DeclarationSourceFile* -  *ImplementationSourceFile:* -   *ImplementationScript* +  *ImplementationSourceFile:* +   *ImplementationScript*    *ImplementationModule* -  *DeclarationSourceFile:* -   *DeclarationScript* +  *DeclarationSourceFile:* +   *DeclarationScript*    *DeclarationModule* Source files with extension '.ts' are ***implementation source files*** containing statements and declarations, and source files with extension '.d.ts' are ***declaration source files*** containing declarations only. @@ -5526,46 +5527,46 @@ Any files included as dependencies in turn have their references analyzed in a t Source files that contain no module import or export declarations are classified as ***scripts***. Scripts form the single ***global namespace*** and entities declared in scripts are in scope everywhere in a program. -  *ImplementationScript:* +  *ImplementationScript:*    *ImplementationScriptElementsopt* -  *ImplementationScriptElements:* -   *ImplementationScriptElement* +  *ImplementationScriptElements:* +   *ImplementationScriptElement*    *ImplementationScriptElements* *ImplementationScriptElement* -  *ImplementationScriptElement:* -   *ImplementationElement* +  *ImplementationScriptElement:* +   *ImplementationElement*    *AmbientModuleDeclaration* -  *ImplementationElement:* -   *Statement* -   *LexicalDeclaration* -   *FunctionDeclaration* -   *GeneratorDeclaration* -   *ClassDeclaration* -   *InterfaceDeclaration* -   *TypeAliasDeclaration* -   *EnumDeclaration* -   *NamespaceDeclaration* -   *AmbientDeclaration* +  *ImplementationElement:* +   *Statement* +   *LexicalDeclaration* +   *FunctionDeclaration* +   *GeneratorDeclaration* +   *ClassDeclaration* +   *InterfaceDeclaration* +   *TypeAliasDeclaration* +   *EnumDeclaration* +   *NamespaceDeclaration* +   *AmbientDeclaration*    *ImportAliasDeclaration* -  *DeclarationScript:* +  *DeclarationScript:*    *DeclarationScriptElementsopt* -  *DeclarationScriptElements:* -   *DeclarationScriptElement* +  *DeclarationScriptElements:* +   *DeclarationScriptElement*    *DeclarationScriptElements* *DeclarationScriptElement* -  *DeclarationScriptElement:* -   *DeclarationElement* +  *DeclarationScriptElement:* +   *DeclarationElement*    *AmbientModuleDeclaration* -  *DeclarationElement:* -   *InterfaceDeclaration* -   *TypeAliasDeclaration* -   *NamespaceDeclaration* -   *AmbientDeclaration* +  *DeclarationElement:* +   *InterfaceDeclaration* +   *TypeAliasDeclaration* +   *NamespaceDeclaration* +   *AmbientDeclaration*    *ImportAliasDeclaration* The initialization order of the scripts that make up the global namespace ultimately depends on the order in which the generated JavaScript files are loaded at run-time (which, for example, may be controlled by <script/> tags that reference the generated JavaScript files). @@ -5574,37 +5575,37 @@ The initialization order of the scripts that make up the global namespace ultima Source files that contain at least one module import or export declaration are considered separate ***modules***. Non-exported entities declared in a module are in scope only in that module, but exported entities can be imported into other modules using import declarations. -  *ImplementationModule:* +  *ImplementationModule:*    *ImplementationModuleElementsopt* -  *ImplementationModuleElements:* -   *ImplementationModuleElement* +  *ImplementationModuleElements:* +   *ImplementationModuleElement*    *ImplementationModuleElements* *ImplementationModuleElement* -  *ImplementationModuleElement:* -   *ImplementationElement* -   *ImportDeclaration* -   *ImportAliasDeclaration* -   *ImportRequireDeclaration* -   *ExportImplementationElement* -   *ExportDefaultImplementationElement* -   *ExportListDeclaration* +  *ImplementationModuleElement:* +   *ImplementationElement* +   *ImportDeclaration* +   *ImportAliasDeclaration* +   *ImportRequireDeclaration* +   *ExportImplementationElement* +   *ExportDefaultImplementationElement* +   *ExportListDeclaration*    *ExportAssignment* -  *DeclarationModule:* +  *DeclarationModule:*    *DeclarationModuleElementsopt* -  *DeclarationModuleElements:* -   *DeclarationModuleElement* +  *DeclarationModuleElements:* +   *DeclarationModuleElement*    *DeclarationModuleElements* *DeclarationModuleElement* -  *DeclarationModuleElement:* -   *DeclarationElement* -   *ImportDeclaration* -   *ImportAliasDeclaration* -   *ExportDeclarationElement* -   *ExportDefaultDeclarationElement* -   *ExportListDeclaration* +  *DeclarationModuleElement:* +   *DeclarationElement* +   *ImportDeclaration* +   *ImportAliasDeclaration* +   *ExportDeclarationElement* +   *ExportDefaultDeclarationElement* +   *ExportListDeclaration*    *ExportAssignment* Initialization order of modules is determined by the module loader being used and is not specified by the TypeScript language. However, it is generally the case that non-circularly dependent modules are automatically loaded and initialized in the correct order. @@ -5614,13 +5615,13 @@ Modules can additionally be declared using *AmbientModuleDeclarations* in declar Below is an example of two modules written in separate source files: ```TypeScript -// -------- main.ts -------- -import { message } from "./log"; +// -------- main.ts -------- +import { message } from "./log"; message("hello"); -// -------- log.ts -------- -export function message(s: string) { - console.log(s); +// -------- log.ts -------- +export function message(s: string) { + console.log(s); } ``` @@ -5701,7 +5702,7 @@ imports the given module without creating any local bindings (this is useful onl Import require declarations exist for backward compatibility with earlier versions of TypeScript. -  *ImportRequireDeclaration:* +  *ImportRequireDeclaration:*    `import` *BindingIdentifier* `=` `require` `(` *StringLiteral* `)` `;` An import require declaration introduces a local identifier that references a given module. The string literal specified in an import require declaration is interpreted as a module name (section [11.3.1](#11.3.1)). The local identifier introduced by the declaration becomes an alias for, and is classified exactly like, the entity exported from the referenced module. Specifically, if the referenced module contains no export assignment the identifier is classified as a value and a namespace, and if the referenced module contains an export assignment the identifier is classified exactly like the entity named in the export assignment. @@ -5728,30 +5729,30 @@ An export declaration declares one or more exported module members. The exported In the body of a module, a declaration can export the declared entity by including an `export` modifier. -  *ExportImplementationElement:* -   `export` *VariableStatement* -   `export` *LexicalDeclaration* -   `export` *FunctionDeclaration* -   `export` *GeneratorDeclaration* -   `export` *ClassDeclaration* -   `export` *InterfaceDeclaration* -   `export` *TypeAliasDeclaration* -   `export` *EnumDeclaration* -   `export` *NamespaceDeclaration* -   `export` *AmbientDeclaration* +  *ExportImplementationElement:* +   `export` *VariableStatement* +   `export` *LexicalDeclaration* +   `export` *FunctionDeclaration* +   `export` *GeneratorDeclaration* +   `export` *ClassDeclaration* +   `export` *InterfaceDeclaration* +   `export` *TypeAliasDeclaration* +   `export` *EnumDeclaration* +   `export` *NamespaceDeclaration* +   `export` *AmbientDeclaration*    `export` *ImportAliasDeclaration* -  *ExportDeclarationElement:* -   `export` *InterfaceDeclaration* -   `export` *TypeAliasDeclaration* -   `export` *AmbientDeclaration* +  *ExportDeclarationElement:* +   `export` *InterfaceDeclaration* +   `export` *TypeAliasDeclaration* +   `export` *AmbientDeclaration*    `export` *ImportAliasDeclaration* In addition to introducing a name in the local declaration space of the module, an exported declaration introduces the same name with the same classification in the module's export declaration space. For example, the declaration ```TypeScript -export function point(x: number, y: number) { - return { x, y }; +export function point(x: number, y: number) { + return { x, y }; } ``` @@ -5761,30 +5762,30 @@ introduces a local name `point` and an exported name `point` that both reference Export default declarations provide short-hand syntax for exporting an entity named `default`. -  *ExportDefaultImplementationElement:* -   `export` `default` *FunctionDeclaration* -   `export` `default` *GeneratorDeclaration* -   `export` `default` *ClassDeclaration* +  *ExportDefaultImplementationElement:* +   `export` `default` *FunctionDeclaration* +   `export` `default` *GeneratorDeclaration* +   `export` `default` *ClassDeclaration*    `export` `default` *AssignmentExpression* `;` -  *ExportDefaultDeclarationElement:* -   `export` `default` *AmbientFunctionDeclaration* -   `export` `default` *AmbientClassDeclaration* +  *ExportDefaultDeclarationElement:* +   `export` `default` *AmbientFunctionDeclaration* +   `export` `default` *AmbientClassDeclaration*    `export` `default` *IdentifierReference* `;` An *ExportDefaultImplementationElement* or *ExportDefaultDeclarationElement* for a function, generator, or class introduces a value named `default`, and in the case of a class, a type named `default`, in the containing module's export declaration space. The declaration may optionally specify a local name for the exported function, generator, or class. For example, the declaration ```TypeScript -export default function point(x: number, y: number) { - return { x, y }; +export default function point(x: number, y: number) { + return { x, y }; } ``` introduces a local name `point` and an exported name `default` that both reference the function. The declaration is effectively equivalent to ```TypeScript -function point(x: number, y: number) { - return { x, y }; +function point(x: number, y: number) { + return { x, y }; } export default point; @@ -5793,8 +5794,8 @@ export default point; which again is equivalent to ```TypeScript -function point(x: number, y: number) { - return { x, y }; +function point(x: number, y: number) { + return { x, y }; } export { point as default }; @@ -5803,13 +5804,13 @@ export { point as default }; An *ExportDefaultImplementationElement* or *ExportDefaultDeclarationElement* for an expression consisting of a single identifier must name an entity declared in the current module or the global namespace. The declaration introduces an entity named `default`, with the same classification as the referenced entity, in the containing module's export declaration space. For example, the declarations ```TypeScript -interface Point { - x: number; - y: number; +interface Point { + x: number; + y: number; } -function Point(x: number, y: number): Point { - return { x, y }; +function Point(x: number, y: number): Point { + return { x, y }; } export default Point; @@ -5829,9 +5830,9 @@ introduces an exported value named `default` of type string. An export list declaration exports one or more entities from the current module or a specified module. -  *ExportListDeclaration:* -   `export` `*` *FromClause* `;` -   `export` *ExportClause* *FromClause* `;` +  *ExportListDeclaration:* +   `export` `*` *FromClause* `;` +   `export` *ExportClause* *FromClause* `;`    `export` *ExportClause* `;` An *ExportListDeclaration* without a *FromClause* exports entities from the current module. In a declaration of the form @@ -5882,7 +5883,7 @@ If a module contains an export assignment it is an error for the module to also Export assignments exist for backward compatibility with earlier versions of TypeScript. An export assignment designates a module member as the entity to be exported in place of the module itself. -  *ExportAssignment:* +  *ExportAssignment:*    `export` `=` *IdentifierReference* `;` A module containing an export assignment can be imported using an import require declaration ([11.3.3](#11.3.3)), and the local alias introduced by the import require declaration then takes on all meanings of the identifier named in the export assignment. @@ -5894,9 +5895,9 @@ Assume the following example resides in the file 'point.ts': ```TypeScript export = Point; -class Point { - constructor(public x: number, public y: number) { } - static origin = new Point(0, 0); +class Point { + constructor(public x: number, public y: number) { } + static origin = new Point(0, 0); } ``` @@ -5905,7 +5906,7 @@ When 'point.ts' is imported in another module, the import alias references the e ```TypeScript import Pt = require("./point"); -var p1 = new Pt(10, 20); +var p1 = new Pt(10, 20); var p2 = Pt.origin; ``` @@ -5920,16 +5921,16 @@ The 'main' and 'log' example from section [11.3](#11.3) above generates the foll File main.js: ```TypeScript -var log_1 = require("./log"); +var log_1 = require("./log"); log_1.message("hello"); ``` File log.js: ```TypeScript -function message(s) { - console.log(s); -} +function message(s) { + console.log(s); +} exports.message = message; ``` @@ -5942,29 +5943,29 @@ File geometry.ts: ```TypeScript export interface Point { x: number; y: number }; -export function point(x: number, y: number): Point { - return { x, y }; +export function point(x: number, y: number): Point { + return { x, y }; } ``` File game.ts: ```TypeScript -import * as g from "./geometry"; +import * as g from "./geometry"; let p = g.point(10, 20); ``` The 'game' module references the imported 'geometry' module in an expression (through its alias 'g') and a 'require' call is therefore included in the emitted JavaScript: ```TypeScript -var g = require("./geometry"); +var g = require("./geometry"); var p = g.point(10, 20); ``` Had the 'game' module instead been written to only reference 'geometry' in a type position ```TypeScript -import * as g from "./geometry"; +import * as g from "./geometry"; let p: g.Point = { x: 10, y: 20 }; ``` @@ -5983,19 +5984,19 @@ The "main" and "log" example from above generates the following JavaScript code File main.js: ```TypeScript -define(["require", "exports", "./log"], function(require, exports, log_1) { - log_1.message("hello"); +define(["require", "exports", "./log"], function(require, exports, log_1) { + log_1.message("hello"); } ``` File log.js: ```TypeScript -define(["require", "exports"], function(require, exports) { - function message(s) { - console.log(s); - } - exports.message = message; +define(["require", "exports"], function(require, exports) { + function message(s) { + console.log(s); + } + exports.message = message; } ``` @@ -6011,27 +6012,27 @@ Ambient declarations are used to provide static typing over existing JavaScript Ambient declarations are written using the `declare` keyword and can declare variables, functions, classes, enums, namespaces, or modules. -  *AmbientDeclaration:* -   `declare` *AmbientVariableDeclaration* -   `declare` *AmbientFunctionDeclaration* -   `declare` *AmbientClassDeclaration* -   `declare` *AmbientEnumDeclaration* +  *AmbientDeclaration:* +   `declare` *AmbientVariableDeclaration* +   `declare` *AmbientFunctionDeclaration* +   `declare` *AmbientClassDeclaration* +   `declare` *AmbientEnumDeclaration*    `declare` *AmbientNamespaceDeclaration* ### 12.1.1 Ambient Variable Declarations An ambient variable declaration introduces a variable in the containing declaration space. -  *AmbientVariableDeclaration:* -   `var` *AmbientBindingList* `;` -   `let` *AmbientBindingList* `;` +  *AmbientVariableDeclaration:* +   `var` *AmbientBindingList* `;` +   `let` *AmbientBindingList* `;`    `const` *AmbientBindingList* `;` -  *AmbientBindingList:* -   *AmbientBinding* +  *AmbientBindingList:* +   *AmbientBinding*    *AmbientBindingList* `,` *AmbientBinding* -  *AmbientBinding:* +  *AmbientBinding:*    *BindingIdentifier* *TypeAnnotationopt* An ambient variable declaration may optionally include a type annotation. If no type annotation is present, the variable is assumed to have type Any. @@ -6042,7 +6043,7 @@ An ambient variable declaration does not permit an initializer expression to be An ambient function declaration introduces a function in the containing declaration space. -  *AmbientFunctionDeclaration:* +  *AmbientFunctionDeclaration:*    `function` *BindingIdentifier* *CallSignature* `;` Ambient functions may be overloaded by specifying multiple ambient function declarations with the same name, but it is an error to declare multiple overloads that are considered identical (section [3.11.2](#3.11.2)) or differ only in their return types. @@ -6053,33 +6054,33 @@ Ambient function declarations cannot specify a function bodies and do not permit An ambient class declaration declares a class type and a constructor function in the containing declaration space. -  *AmbientClassDeclaration:* +  *AmbientClassDeclaration:*    `class` *BindingIdentifier* *TypeParametersopt* *ClassHeritage* `{` *AmbientClassBody* `}` -  *AmbientClassBody:* +  *AmbientClassBody:*    *AmbientClassBodyElementsopt* -  *AmbientClassBodyElements:* -   *AmbientClassBodyElement* +  *AmbientClassBodyElements:* +   *AmbientClassBodyElement*    *AmbientClassBodyElements* *AmbientClassBodyElement* -  *AmbientClassBodyElement:* -   *AmbientConstructorDeclaration* -   *AmbientPropertyMemberDeclaration* +  *AmbientClassBodyElement:* +   *AmbientConstructorDeclaration* +   *AmbientPropertyMemberDeclaration*    *IndexSignature* -  *AmbientConstructorDeclaration:* +  *AmbientConstructorDeclaration:*    `constructor` `(` *ParameterListopt* `)` `;` -  *AmbientPropertyMemberDeclaration:* -   *AccessibilityModifieropt* `static`*opt* *PropertyName* *TypeAnnotationopt* `;` +  *AmbientPropertyMemberDeclaration:* +   *AccessibilityModifieropt* `static`*opt* *PropertyName* *TypeAnnotationopt* `;`    *AccessibilityModifieropt* `static`*opt* *PropertyName* *CallSignature* `;` ### 12.1.4 Ambient Enum Declarations An ambient enum is grammatically equivalent to a non-ambient enum declaration. -  *AmbientEnumDeclaration:* +  *AmbientEnumDeclaration:*    *EnumDeclaration* Ambient enum declarations differ from non-ambient enum declarations in two ways: @@ -6093,24 +6094,24 @@ Ambient enum declarations are otherwise processed in the same manner as non-ambi An ambient namespace declaration declares a namespace. -  *AmbientNamespaceDeclaration:* +  *AmbientNamespaceDeclaration:*    `namespace` *IdentifierPath* `{` *AmbientNamespaceBody* `}` -  *AmbientNamespaceBody:* +  *AmbientNamespaceBody:*    *AmbientNamespaceElementsopt* -  *AmbientNamespaceElements:* -   *AmbientNamespaceElement* +  *AmbientNamespaceElements:* +   *AmbientNamespaceElement*    *AmbientNamespaceElements* *AmbientNamespaceElement* -  *AmbientNamespaceElement:* -   `export`*opt* *AmbientVariableDeclaration* -   `export`*opt* *AmbientLexicalDeclaration* -   `export`*opt* *AmbientFunctionDeclaration* -   `export`*opt* *AmbientClassDeclaration* -   `export`*opt* *InterfaceDeclaration* -   `export`*opt* *AmbientEnumDeclaration* -   `export`*opt* *AmbientNamespaceDeclaration* +  *AmbientNamespaceElement:* +   `export`*opt* *AmbientVariableDeclaration* +   `export`*opt* *AmbientLexicalDeclaration* +   `export`*opt* *AmbientFunctionDeclaration* +   `export`*opt* *AmbientClassDeclaration* +   `export`*opt* *InterfaceDeclaration* +   `export`*opt* *AmbientEnumDeclaration* +   `export`*opt* *AmbientNamespaceDeclaration*    `export`*opt* *ImportAliasDeclaration* Except for *ImportAliasDeclarations*, *AmbientNamespaceElements* always declare exported entities regardless of whether they include the optional `export` modifier. @@ -6119,7 +6120,7 @@ Except for *ImportAliasDeclarations*, *AmbientNamespaceElements* always declare An *AmbientModuleDeclaration* declares a module. This type of declaration is permitted only at the top level in a source file that contributes to the global namespace (section [11.1](#11.1)). The *StringLiteral* must specify a top-level module name. Relative module names are not permitted. -  *AmbientModuleDeclaration:* +  *AmbientModuleDeclaration:*    `declare` `module` *StringLiteral* `{`  *DeclarationModule* `}` An *ImportRequireDeclaration* in an *AmbientModuleDeclaration* may reference other modules only through top-level module names. Relative module names are not permitted. @@ -6129,21 +6130,21 @@ If an ambient module declaration includes an export assignment, it is an error f Ambient modules are "open-ended" and ambient module declarations with the same string literal name contribute to a single module. For example, the following two declarations of a module 'io' might be located in separate source files. ```TypeScript -declare module "io" { - export function readFile(filename: string): string; +declare module "io" { + export function readFile(filename: string): string; } -declare module "io" { - export function writeFile(filename: string, data: string): void; +declare module "io" { + export function writeFile(filename: string, data: string): void; } ``` This has the same effect as a single combined declaration: ```TypeScript -declare module "io" { - export function readFile(filename: string): string; - export function writeFile(filename: string, data: string): void; +declare module "io" { + export function readFile(filename: string): string; + export function writeFile(filename: string, data: string): void; } ``` @@ -6155,584 +6156,583 @@ This appendix contains a summary of the grammar found in the main document. As d ## A.1 Types -  *TypeParameters:* +  *TypeParameters:*    `<` *TypeParameterList* `>` -  *TypeParameterList:* -   *TypeParameter* +  *TypeParameterList:* +   *TypeParameter*    *TypeParameterList* `,` *TypeParameter* -  *TypeParameter:* +  *TypeParameter:*    *BindingIdentifier* *Constraintopt* -  *Constraint:* +  *Constraint:*    `extends` *Type* -  *TypeArguments:* +  *TypeArguments:*    `<` *TypeArgumentList* `>` -  *TypeArgumentList:* -   *TypeArgument* +  *TypeArgumentList:* +   *TypeArgument*    *TypeArgumentList* `,` *TypeArgument* -  *TypeArgument:* +  *TypeArgument:*    *Type* -  *Type:* -   *UnionOrIntersectionOrPrimaryType* -   *FunctionType* +  *Type:* +   *UnionOrIntersectionOrPrimaryType* +   *FunctionType*    *ConstructorType* -  *UnionOrIntersectionOrPrimaryType:* -   *UnionType* +  *UnionOrIntersectionOrPrimaryType:* +   *UnionType*    *IntersectionOrPrimaryType* -  *IntersectionOrPrimaryType:* -   *IntersectionType* +  *IntersectionOrPrimaryType:* +   *IntersectionType*    *PrimaryType* -  *PrimaryType:* -   *ParenthesizedType* -   *PredefinedType* -   *TypeReference* -   *ObjectType* -   *ArrayType* -   *TupleType* -   *TypeQuery* +  *PrimaryType:* +   *ParenthesizedType* +   *PredefinedType* +   *TypeReference* +   *ObjectType* +   *ArrayType* +   *TupleType* +   *TypeQuery*    *ThisType* -  *ParenthesizedType:* +  *ParenthesizedType:*    `(` *Type* `)` -  *PredefinedType:* -   `any` -   `number` -   `boolean` -   `string` -   `symbol` +  *PredefinedType:* +   `any` +   `number` +   `boolean` +   `string` +   `symbol`    `void` -  *TypeReference:* +  *TypeReference:*    *TypeName* *[no LineTerminator here]* *TypeArgumentsopt* -  *TypeName:* -   *IdentifierReference* +  *TypeName:* +   *IdentifierReference*    *NamespaceName* `.` *IdentifierReference* -  *NamespaceName:* -   *IdentifierReference* +  *NamespaceName:* +   *IdentifierReference*    *NamespaceName* `.` *IdentifierReference* -  *ObjectType:* +  *ObjectType:*    `{` *TypeBodyopt* `}` -  *TypeBody:* -   *TypeMemberList* `;`*opt* +  *TypeBody:* +   *TypeMemberList* `;`*opt*    *TypeMemberList* `,`*opt* -  *TypeMemberList:* -   *TypeMember* -   *TypeMemberList* `;` *TypeMember* +  *TypeMemberList:* +   *TypeMember* +   *TypeMemberList* `;` *TypeMember*    *TypeMemberList* `,` *TypeMember* -  *TypeMember:* -   *PropertySignature* -   *CallSignature* -   *ConstructSignature* -   *IndexSignature* +  *TypeMember:* +   *PropertySignature* +   *CallSignature* +   *ConstructSignature* +   *IndexSignature*    *MethodSignature* -  *ArrayType:* +  *ArrayType:*    *PrimaryType* *[no LineTerminator here]* `[` `]` -  *TupleType:* +  *TupleType:*    `[` *TupleElementTypes* `]` -  *TupleElementTypes:* -   *TupleElementType* +  *TupleElementTypes:* +   *TupleElementType*    *TupleElementTypes* `,` *TupleElementType* -  *TupleElementType:* +  *TupleElementType:*    *Type* -  *UnionType:* +  *UnionType:*    *UnionOrIntersectionOrPrimaryType* `|` *IntersectionOrPrimaryType* -  *IntersectionType:* +  *IntersectionType:*    *IntersectionOrPrimaryType* `&` *PrimaryType* -  *FunctionType:* +  *FunctionType:*    *TypeParametersopt* `(` *ParameterListopt* `)` `=>` *Type* -  *ConstructorType:* +  *ConstructorType:*    `new` *TypeParametersopt* `(` *ParameterListopt* `)` `=>` *Type* -  *TypeQuery:* +  *TypeQuery:*    `typeof` *TypeQueryExpression* -  *TypeQueryExpression:* -   *IdentifierReference* +  *TypeQueryExpression:* +   *IdentifierReference*    *TypeQueryExpression* `.` *IdentifierName* -  *ThisType:* +  *ThisType:*    `this` -  *PropertySignature:* +  *PropertySignature:*    *PropertyName* `?`*opt* *TypeAnnotationopt* -  *PropertyName:* -   *IdentifierName* -   *StringLiteral* +  *PropertyName:* +   *IdentifierName* +   *StringLiteral*    *NumericLiteral* -  *TypeAnnotation:* +  *TypeAnnotation:*    `:` *Type* -  *CallSignature:* +  *CallSignature:*    *TypeParametersopt* `(` *ParameterListopt* `)` *TypeAnnotationopt* -  *ParameterList:* -   *RequiredParameterList* -   *OptionalParameterList* -   *RestParameter* -   *RequiredParameterList* `,` *OptionalParameterList* -   *RequiredParameterList* `,` *RestParameter* -   *OptionalParameterList* `,` *RestParameter* +  *ParameterList:* +   *RequiredParameterList* +   *OptionalParameterList* +   *RestParameter* +   *RequiredParameterList* `,` *OptionalParameterList* +   *RequiredParameterList* `,` *RestParameter* +   *OptionalParameterList* `,` *RestParameter*    *RequiredParameterList* `,` *OptionalParameterList* `,` *RestParameter* -  *RequiredParameterList:* -   *RequiredParameter* +  *RequiredParameterList:* +   *RequiredParameter*    *RequiredParameterList* `,` *RequiredParameter* -  *RequiredParameter:* -   *AccessibilityModifieropt* *BindingIdentifierOrPattern* *TypeAnnotationopt* +  *RequiredParameter:* +   *AccessibilityModifieropt* *BindingIdentifierOrPattern* *TypeAnnotationopt*    *BindingIdentifier* `:` *StringLiteral* -  *AccessibilityModifier:* -   `public` -   `private` +  *AccessibilityModifier:* +   `public` +   `private`    `protected` -  *BindingIdentifierOrPattern:* -   *BindingIdentifier* +  *BindingIdentifierOrPattern:* +   *BindingIdentifier*    *BindingPattern* -  *OptionalParameterList:* -   *OptionalParameter* +  *OptionalParameterList:* +   *OptionalParameter*    *OptionalParameterList* `,` *OptionalParameter* -  *OptionalParameter:* -   *AccessibilityModifieropt* *BindingIdentifierOrPattern* `?` *TypeAnnotationopt* -   *AccessibilityModifieropt* *BindingIdentifierOrPattern* *TypeAnnotationopt* *Initializer* +  *OptionalParameter:* +   *AccessibilityModifieropt* *BindingIdentifierOrPattern* `?` *TypeAnnotationopt* +   *AccessibilityModifieropt* *BindingIdentifierOrPattern* *TypeAnnotationopt* *Initializer*    *BindingIdentifier* `?` `:` *StringLiteral* -  *RestParameter:* +  *RestParameter:*    `...` *BindingIdentifier* *TypeAnnotationopt* -  *ConstructSignature:* +  *ConstructSignature:*    `new` *TypeParametersopt* `(` *ParameterListopt* `)` *TypeAnnotationopt* -  *IndexSignature:* -   `[` *BindingIdentifier* `:` `string` `]` *TypeAnnotation* +  *IndexSignature:* +   `[` *BindingIdentifier* `:` `string` `]` *TypeAnnotation*    `[` *BindingIdentifier* `:` `number` `]` *TypeAnnotation* -  *MethodSignature:* +  *MethodSignature:*    *PropertyName* `?`*opt* *CallSignature* -  *TypeAliasDeclaration:* +  *TypeAliasDeclaration:*    `type` *BindingIdentifier* *TypeParametersopt* `=` *Type* `;` ## A.2 Expressions -  *PropertyDefinition:* *( Modified )* -   *IdentifierReference* -   *CoverInitializedName* -   *PropertyName* `:` *AssignmentExpression* -   *PropertyName* *CallSignature* `{` *FunctionBody* `}` -   *GetAccessor* +  *PropertyDefinition:* *( Modified )* +   *IdentifierReference* +   *CoverInitializedName* +   *PropertyName* `:` *AssignmentExpression* +   *PropertyName* *CallSignature* `{` *FunctionBody* `}` +   *GetAccessor*    *SetAccessor* -  *GetAccessor:* +  *GetAccessor:*    `get` *PropertyName* `(` `)` *TypeAnnotationopt* `{` *FunctionBody* `}` -  *SetAccessor:* +  *SetAccessor:*    `set` *PropertyName* `(` *BindingIdentifierOrPattern* *TypeAnnotationopt* `)` `{` *FunctionBody* `}` -  *FunctionExpression:* *( Modified )* +  *FunctionExpression:* *( Modified )*    `function` *BindingIdentifieropt* *CallSignature* `{` *FunctionBody* `}` -  *ArrowFormalParameters:* *( Modified )* +  *ArrowFormalParameters:* *( Modified )*    *CallSignature* -  *Arguments:* *( Modified )* +  *Arguments:* *( Modified )*    *TypeArgumentsopt* `(` *ArgumentListopt* `)` -  *UnaryExpression:* *( Modified )* -   … +  *UnaryExpression:* *( Modified )* +   …    `<` *Type* `>` *UnaryExpression* ## A.3 Statements -  *Declaration:* *( Modified )* -   … -   *InterfaceDeclaration* -   *TypeAliasDeclaration* +  *Declaration:* *( Modified )* +   … +   *InterfaceDeclaration* +   *TypeAliasDeclaration*    *EnumDeclaration* -  *VariableDeclaration:* *( Modified )* -   *SimpleVariableDeclaration* +  *VariableDeclaration:* *( Modified )* +   *SimpleVariableDeclaration*    *DestructuringVariableDeclaration* -  *SimpleVariableDeclaration:* +  *SimpleVariableDeclaration:*    *BindingIdentifier* *TypeAnnotationopt* *Initializeropt* -  *DestructuringVariableDeclaration:* +  *DestructuringVariableDeclaration:*    *BindingPattern* *TypeAnnotationopt* *Initializer* -  *LexicalBinding:* *( Modified )* -   *SimpleLexicalBinding* +  *LexicalBinding:* *( Modified )* +   *SimpleLexicalBinding*    *DestructuringLexicalBinding* -  *SimpleLexicalBinding:* +  *SimpleLexicalBinding:*    *BindingIdentifier* *TypeAnnotationopt* *Initializeropt* -  *DestructuringLexicalBinding:* +  *DestructuringLexicalBinding:*    *BindingPattern* *TypeAnnotationopt* *Initializeropt* ## A.4 Functions -  *FunctionDeclaration:* *( Modified )* -   `function` *BindingIdentifieropt* *CallSignature* `{` *FunctionBody* `}` +  *FunctionDeclaration:* *( Modified )* +   `function` *BindingIdentifieropt* *CallSignature* `{` *FunctionBody* `}`    `function` *BindingIdentifieropt* *CallSignature* `;` ## A.5 Interfaces -  *InterfaceDeclaration:* +  *InterfaceDeclaration:*    `interface` *BindingIdentifier* *TypeParametersopt* *InterfaceExtendsClauseopt* *ObjectType* -  *InterfaceExtendsClause:* +  *InterfaceExtendsClause:*    `extends` *ClassOrInterfaceTypeList* -  *ClassOrInterfaceTypeList:* -   *ClassOrInterfaceType* +  *ClassOrInterfaceTypeList:* +   *ClassOrInterfaceType*    *ClassOrInterfaceTypeList* `,` *ClassOrInterfaceType* -  *ClassOrInterfaceType:* +  *ClassOrInterfaceType:*    *TypeReference* ## A.6 Classes -  *ClassDeclaration:* *( Modified )* +  *ClassDeclaration:* *( Modified )*    `class` *BindingIdentifieropt* *TypeParametersopt* *ClassHeritage* `{` *ClassBody* `}` -  *ClassHeritage:* *( Modified )* +  *ClassHeritage:* *( Modified )*    *ClassExtendsClauseopt* *ImplementsClauseopt* -  *ClassExtendsClause:* +  *ClassExtendsClause:*    `extends`  *ClassType* -  *ClassType:* +  *ClassType:*    *TypeReference* -  *ImplementsClause:* +  *ImplementsClause:*    `implements` *ClassOrInterfaceTypeList* -  *ClassElement:* *( Modified )* -   *ConstructorDeclaration* -   *PropertyMemberDeclaration* +  *ClassElement:* *( Modified )* +   *ConstructorDeclaration* +   *PropertyMemberDeclaration*    *IndexMemberDeclaration* -  *ConstructorDeclaration:* -   *AccessibilityModifieropt* `constructor` `(` *ParameterListopt* `)` `{` *FunctionBody* `}` +  *ConstructorDeclaration:* +   *AccessibilityModifieropt* `constructor` `(` *ParameterListopt* `)` `{` *FunctionBody* `}`    *AccessibilityModifieropt* `constructor` `(` *ParameterListopt* `)` `;` -  *PropertyMemberDeclaration:* -   *MemberVariableDeclaration* -   *MemberFunctionDeclaration* +  *PropertyMemberDeclaration:* +   *MemberVariableDeclaration* +   *MemberFunctionDeclaration*    *MemberAccessorDeclaration* -  *MemberVariableDeclaration:* +  *MemberVariableDeclaration:*    *AccessibilityModifieropt* `static`*opt* *PropertyName* *TypeAnnotationopt* *Initializeropt* `;` -  *MemberFunctionDeclaration:* -   *AccessibilityModifieropt* `static`*opt* *PropertyName* *CallSignature* `{` *FunctionBody* `}` +  *MemberFunctionDeclaration:* +   *AccessibilityModifieropt* `static`*opt* *PropertyName* *CallSignature* `{` *FunctionBody* `}`    *AccessibilityModifieropt* `static`*opt* *PropertyName* *CallSignature* `;` -  *MemberAccessorDeclaration:* -   *AccessibilityModifieropt* `static`*opt* *GetAccessor* +  *MemberAccessorDeclaration:* +   *AccessibilityModifieropt* `static`*opt* *GetAccessor*    *AccessibilityModifieropt* `static`*opt* *SetAccessor* -  *IndexMemberDeclaration:* +  *IndexMemberDeclaration:*    *IndexSignature* `;` ## A.7 Enums -  *EnumDeclaration:* +  *EnumDeclaration:*    `const`*opt* `enum` *BindingIdentifier* `{` *EnumBodyopt* `}` -  *EnumBody:* +  *EnumBody:*    *EnumMemberList* `,`*opt* -  *EnumMemberList:* -   *EnumMember* +  *EnumMemberList:* +   *EnumMember*    *EnumMemberList* `,` *EnumMember* -  *EnumMember:* -   *PropertyName* +  *EnumMember:* +   *PropertyName*    *PropertyName* = *EnumValue* -  *EnumValue:* +  *EnumValue:*    *AssignmentExpression* ## A.8 Namespaces -  *NamespaceDeclaration:* +  *NamespaceDeclaration:*    `namespace` *IdentifierPath* `{` *NamespaceBody* `}` -  *IdentifierPath:* -   *BindingIdentifier* +  *IdentifierPath:* +   *BindingIdentifier*    *IdentifierPath* `.` *BindingIdentifier* -  *NamespaceBody:* +  *NamespaceBody:*    *NamespaceElementsopt* -  *NamespaceElements:* -   *NamespaceElement* +  *NamespaceElements:* +   *NamespaceElement*    *NamespaceElements* *NamespaceElement* -  *NamespaceElement:* -   *Statement* -   *LexicalDeclaration* -   *FunctionDeclaration* -   *GeneratorDeclaration* -   *ClassDeclaration* -   *InterfaceDeclaration* -   *TypeAliasDeclaration* -   *EnumDeclaration* -   *NamespaceDeclaration -   AmbientDeclaration -   ImportAliasDeclaration +  *NamespaceElement:* +   *Statement* +   *LexicalDeclaration* +   *FunctionDeclaration* +   *GeneratorDeclaration* +   *ClassDeclaration* +   *InterfaceDeclaration* +   *TypeAliasDeclaration* +   *EnumDeclaration* +   *NamespaceDeclaration +   AmbientDeclaration +   ImportAliasDeclaration    ExportNamespaceElement* -  *ExportNamespaceElement:* -   `export` *VariableStatement* -   `export` *LexicalDeclaration* -   `export` *FunctionDeclaration* -   `export` *GeneratorDeclaration* -   `export` *ClassDeclaration* -   `export` *InterfaceDeclaration* -   `export` *TypeAliasDeclaration* -   `export` *EnumDeclaration* -   `export` *NamespaceDeclaration* -   `export` *AmbientDeclaration* +  *ExportNamespaceElement:* +   `export` *VariableStatement* +   `export` *LexicalDeclaration* +   `export` *FunctionDeclaration* +   `export` *GeneratorDeclaration* +   `export` *ClassDeclaration* +   `export` *InterfaceDeclaration* +   `export` *TypeAliasDeclaration* +   `export` *EnumDeclaration* +   `export` *NamespaceDeclaration* +   `export` *AmbientDeclaration*    `export` *ImportAliasDeclaration* -  *ImportAliasDeclaration:* +  *ImportAliasDeclaration:*    `import` *BindingIdentifier* `=` *EntityName* `;` -  *EntityName:* -   *NamespaceName* +  *EntityName:* +   *NamespaceName*    *NamespaceName* `.` *IdentifierReference* ## A.9 Scripts and Modules -  *SourceFile:* -   *ImplementationSourceFile* +  *SourceFile:* +   *ImplementationSourceFile*    *DeclarationSourceFile* -  *ImplementationSourceFile:* -   *ImplementationScript* +  *ImplementationSourceFile:* +   *ImplementationScript*    *ImplementationModule* -  *DeclarationSourceFile:* -   *DeclarationScript* +  *DeclarationSourceFile:* +   *DeclarationScript*    *DeclarationModule* -  *ImplementationScript:* +  *ImplementationScript:*    *ImplementationScriptElementsopt* -  *ImplementationScriptElements:* -   *ImplementationScriptElement* +  *ImplementationScriptElements:* +   *ImplementationScriptElement*    *ImplementationScriptElements* *ImplementationScriptElement* -  *ImplementationScriptElement:* -   *ImplementationElement* +  *ImplementationScriptElement:* +   *ImplementationElement*    *AmbientModuleDeclaration* -  *ImplementationElement:* -   *Statement* -   *LexicalDeclaration* -   *FunctionDeclaration* -   *GeneratorDeclaration* -   *ClassDeclaration* -   *InterfaceDeclaration* -   *TypeAliasDeclaration* -   *EnumDeclaration* -   *NamespaceDeclaration* -   *AmbientDeclaration* +  *ImplementationElement:* +   *Statement* +   *LexicalDeclaration* +   *FunctionDeclaration* +   *GeneratorDeclaration* +   *ClassDeclaration* +   *InterfaceDeclaration* +   *TypeAliasDeclaration* +   *EnumDeclaration* +   *NamespaceDeclaration* +   *AmbientDeclaration*    *ImportAliasDeclaration* -  *DeclarationScript:* +  *DeclarationScript:*    *DeclarationScriptElementsopt* -  *DeclarationScriptElements:* -   *DeclarationScriptElement* +  *DeclarationScriptElements:* +   *DeclarationScriptElement*    *DeclarationScriptElements* *DeclarationScriptElement* -  *DeclarationScriptElement:* -   *DeclarationElement* +  *DeclarationScriptElement:* +   *DeclarationElement*    *AmbientModuleDeclaration* -  *DeclarationElement:* -   *InterfaceDeclaration* -   *TypeAliasDeclaration* -   *NamespaceDeclaration* -   *AmbientDeclaration* +  *DeclarationElement:* +   *InterfaceDeclaration* +   *TypeAliasDeclaration* +   *NamespaceDeclaration* +   *AmbientDeclaration*    *ImportAliasDeclaration* -  *ImplementationModule:* +  *ImplementationModule:*    *ImplementationModuleElementsopt* -  *ImplementationModuleElements:* -   *ImplementationModuleElement* +  *ImplementationModuleElements:* +   *ImplementationModuleElement*    *ImplementationModuleElements* *ImplementationModuleElement* -  *ImplementationModuleElement:* -   *ImplementationElement* -   *ImportDeclaration* -   *ImportAliasDeclaration* -   *ImportRequireDeclaration* -   *ExportImplementationElement* -   *ExportDefaultImplementationElement* -   *ExportListDeclaration* +  *ImplementationModuleElement:* +   *ImplementationElement* +   *ImportDeclaration* +   *ImportAliasDeclaration* +   *ImportRequireDeclaration* +   *ExportImplementationElement* +   *ExportDefaultImplementationElement* +   *ExportListDeclaration*    *ExportAssignment* -  *DeclarationModule:* +  *DeclarationModule:*    *DeclarationModuleElementsopt* -  *DeclarationModuleElements:* -   *DeclarationModuleElement* +  *DeclarationModuleElements:* +   *DeclarationModuleElement*    *DeclarationModuleElements* *DeclarationModuleElement* -  *DeclarationModuleElement:* -   *DeclarationElement* -   *ImportDeclaration* -   *ImportAliasDeclaration* -   *ExportDeclarationElement* -   *ExportDefaultDeclarationElement* -   *ExportListDeclaration* +  *DeclarationModuleElement:* +   *DeclarationElement* +   *ImportDeclaration* +   *ImportAliasDeclaration* +   *ExportDeclarationElement* +   *ExportDefaultDeclarationElement* +   *ExportListDeclaration*    *ExportAssignment* -  *ImportRequireDeclaration:* +  *ImportRequireDeclaration:*    `import` *BindingIdentifier* `=` `require` `(` *StringLiteral* `)` `;` -  *ExportImplementationElement:* -   `export` *VariableStatement* -   `export` *LexicalDeclaration* -   `export` *FunctionDeclaration* -   `export` *GeneratorDeclaration* -   `export` *ClassDeclaration* -   `export` *InterfaceDeclaration* -   `export` *TypeAliasDeclaration* -   `export` *EnumDeclaration* -   `export` *NamespaceDeclaration* -   `export` *AmbientDeclaration* +  *ExportImplementationElement:* +   `export` *VariableStatement* +   `export` *LexicalDeclaration* +   `export` *FunctionDeclaration* +   `export` *GeneratorDeclaration* +   `export` *ClassDeclaration* +   `export` *InterfaceDeclaration* +   `export` *TypeAliasDeclaration* +   `export` *EnumDeclaration* +   `export` *NamespaceDeclaration* +   `export` *AmbientDeclaration*    `export` *ImportAliasDeclaration* -  *ExportDeclarationElement:* -   `export` *InterfaceDeclaration* -   `export` *TypeAliasDeclaration* -   `export` *AmbientDeclaration* +  *ExportDeclarationElement:* +   `export` *InterfaceDeclaration* +   `export` *TypeAliasDeclaration* +   `export` *AmbientDeclaration*    `export` *ImportAliasDeclaration* -  *ExportDefaultImplementationElement:* -   `export` `default` *FunctionDeclaration* -   `export` `default` *GeneratorDeclaration* -   `export` `default` *ClassDeclaration* +  *ExportDefaultImplementationElement:* +   `export` `default` *FunctionDeclaration* +   `export` `default` *GeneratorDeclaration* +   `export` `default` *ClassDeclaration*    `export` `default` *AssignmentExpression* `;` -  *ExportDefaultDeclarationElement:* -   `export` `default` *AmbientFunctionDeclaration* -   `export` `default` *AmbientClassDeclaration* +  *ExportDefaultDeclarationElement:* +   `export` `default` *AmbientFunctionDeclaration* +   `export` `default` *AmbientClassDeclaration*    `export` `default` *IdentifierReference* `;` -  *ExportListDeclaration:* -   `export` `*` *FromClause* `;` -   `export` *ExportClause* *FromClause* `;` +  *ExportListDeclaration:* +   `export` `*` *FromClause* `;` +   `export` *ExportClause* *FromClause* `;`    `export` *ExportClause* `;` -  *ExportAssignment:* +  *ExportAssignment:*    `export` `=` *IdentifierReference* `;` ## A.10 Ambients -  *AmbientDeclaration:* -   `declare` *AmbientVariableDeclaration* -   `declare` *AmbientFunctionDeclaration* -   `declare` *AmbientClassDeclaration* -   `declare` *AmbientEnumDeclaration* +  *AmbientDeclaration:* +   `declare` *AmbientVariableDeclaration* +   `declare` *AmbientFunctionDeclaration* +   `declare` *AmbientClassDeclaration* +   `declare` *AmbientEnumDeclaration*    `declare` *AmbientNamespaceDeclaration* -  *AmbientVariableDeclaration:* -   `var` *AmbientBindingList* `;` -   `let` *AmbientBindingList* `;` +  *AmbientVariableDeclaration:* +   `var` *AmbientBindingList* `;` +   `let` *AmbientBindingList* `;`    `const` *AmbientBindingList* `;` -  *AmbientBindingList:* -   *AmbientBinding* +  *AmbientBindingList:* +   *AmbientBinding*    *AmbientBindingList* `,` *AmbientBinding* -  *AmbientBinding:* +  *AmbientBinding:*    *BindingIdentifier* *TypeAnnotationopt* -  *AmbientFunctionDeclaration:* +  *AmbientFunctionDeclaration:*    `function` *BindingIdentifier* *CallSignature* `;` -  *AmbientClassDeclaration:* +  *AmbientClassDeclaration:*    `class` *BindingIdentifier* *TypeParametersopt* *ClassHeritage* `{` *AmbientClassBody* `}` -  *AmbientClassBody:* +  *AmbientClassBody:*    *AmbientClassBodyElementsopt* -  *AmbientClassBodyElements:* -   *AmbientClassBodyElement* +  *AmbientClassBodyElements:* +   *AmbientClassBodyElement*    *AmbientClassBodyElements* *AmbientClassBodyElement* -  *AmbientClassBodyElement:* -   *AmbientConstructorDeclaration* -   *AmbientPropertyMemberDeclaration* +  *AmbientClassBodyElement:* +   *AmbientConstructorDeclaration* +   *AmbientPropertyMemberDeclaration*    *IndexSignature* -  *AmbientConstructorDeclaration:* +  *AmbientConstructorDeclaration:*    `constructor` `(` *ParameterListopt* `)` `;` -  *AmbientPropertyMemberDeclaration:* -   *AccessibilityModifieropt* `static`*opt* *PropertyName* *TypeAnnotationopt* `;` +  *AmbientPropertyMemberDeclaration:* +   *AccessibilityModifieropt* `static`*opt* *PropertyName* *TypeAnnotationopt* `;`    *AccessibilityModifieropt* `static`*opt* *PropertyName* *CallSignature* `;` -  *AmbientEnumDeclaration:* +  *AmbientEnumDeclaration:*    *EnumDeclaration* -  *AmbientNamespaceDeclaration:* +  *AmbientNamespaceDeclaration:*    `namespace` *IdentifierPath* `{` *AmbientNamespaceBody* `}` -  *AmbientNamespaceBody:* +  *AmbientNamespaceBody:*    *AmbientNamespaceElementsopt* -  *AmbientNamespaceElements:* -   *AmbientNamespaceElement* +  *AmbientNamespaceElements:* +   *AmbientNamespaceElement*    *AmbientNamespaceElements* *AmbientNamespaceElement* -  *AmbientNamespaceElement:* -   `export`*opt* *AmbientVariableDeclaration* -   `export`*opt* *AmbientLexicalDeclaration* -   `export`*opt* *AmbientFunctionDeclaration* -   `export`*opt* *AmbientClassDeclaration* -   `export`*opt* *InterfaceDeclaration* -   `export`*opt* *AmbientEnumDeclaration* -   `export`*opt* *AmbientNamespaceDeclaration* +  *AmbientNamespaceElement:* +   `export`*opt* *AmbientVariableDeclaration* +   `export`*opt* *AmbientLexicalDeclaration* +   `export`*opt* *AmbientFunctionDeclaration* +   `export`*opt* *AmbientClassDeclaration* +   `export`*opt* *InterfaceDeclaration* +   `export`*opt* *AmbientEnumDeclaration* +   `export`*opt* *AmbientNamespaceDeclaration*    `export`*opt* *ImportAliasDeclaration* -  *AmbientModuleDeclaration:* +  *AmbientModuleDeclaration:*    `declare` `module` *StringLiteral* `{`  *DeclarationModule* `}` - diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b09eae7b19b88..3bd0ad47e5922 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18334,7 +18334,7 @@ namespace ts { for (const prop of getPropertiesOfObjectType(type)) { properties[prop.name] = prop; } - checkImplicitPropertyMemberOverrides(type, properties); + checkAugmentedPropertyMemberOverrides(type, properties); } const implementedTypeNodes = getClassImplementsHeritageClauseElements(node); @@ -18388,14 +18388,21 @@ namespace ts { return forEach(symbol.declarations, d => isClassLike(d) ? d : undefined); } - function checkImplicitPropertyMemberOverrides(type: InterfaceType, propertiesToCheck: Map): void { + function checkAugmentedPropertyMemberOverrides(type: InterfaceType, propertiesToCheck: Map): void { // If the class does not explicitly declare 'extends Object', // declarations that mask 'Object' members ('toString()', 'hasOwnProperty()', etc...) // are considered here. + + // check is disabled in ambient contexts + if (isInAmbientContext(type.symbol.valueDeclaration)) { + return; + } + const objectType = getSymbol(globals, "Object", SymbolFlags.Type); if (!objectType) { return; } + for (const name in propertiesToCheck) { const derived = getTargetSymbol(propertiesToCheck[name]); const derivedDeclarationFlags = getDeclarationModifierFlagsFromSymbol(derived); @@ -18403,25 +18410,31 @@ namespace ts { if (found) { if (compilerOptions.noImplicitOverride) { const foundSymbol = getTargetSymbol(found); - let detail = "masks Object." + symbolToString(found); - // assert that the type of the derived - // property matches that of the base property. + let errorInfo = chainDiagnosticMessages( + undefined, + Diagnostics.Class_member_0_must_be_marked_override_when_noImplicitOverride_is_enabled_augmented_from_Object_1, + symbolToString(derived), + symbolToString(found) + ); if (!isPropertyIdenticalTo(derived, foundSymbol)) { - detail += "). The override declaration (" - + typeToString(getTypeOfSymbol(derived)) - + ") also has a different type signature than the original (" - + typeToString(getTypeOfSymbol(foundSymbol)); + errorInfo = chainDiagnosticMessages( + errorInfo, + Diagnostics.Type_0_is_not_assignable_to_type_1, + typeToString(getTypeOfSymbol(derived)), + typeToString(getTypeOfSymbol(foundSymbol)) + ); } - error(derived.valueDeclaration.name, Diagnostics.Class_member_0_must_be_marked_override_when_noImplicitOverride_is_enabled_1, - symbolToString(derived), detail); + diagnostics.add(createDiagnosticForNodeFromMessageChain(derived.valueDeclaration.name, errorInfo)); } } // No matching property found on the object type. It // is an error for the derived property to falsely // claim 'override'. else if (derivedDeclarationFlags & ModifierFlags.Override) { - error(derived.valueDeclaration.name, Diagnostics.Class_member_0_was_marked_override_but_no_matching_definition_was_found_in_any_supertype_of_1, - symbolToString(derived), typeToString(type)); + error(derived.valueDeclaration.name, + Diagnostics.Class_member_0_was_marked_override_but_no_matching_declaration_was_found_in_any_supertype_of_1, + symbolToString(derived), + typeToString(type)); } } } @@ -18450,6 +18463,8 @@ namespace ts { onlyInDerived[prop.name] = prop; } + const ambient = isInAmbientContext(type.symbol.valueDeclaration); + const baseProperties = getPropertiesOfObjectType(baseType); for (const baseProperty of baseProperties) { const base = getTargetSymbol(baseProperty); @@ -18507,10 +18522,13 @@ namespace ts { // Before accepting the correct case, ensure 'override' is marked if --noImplicitOverride is true. // Abstract members are an exception as override checks are suspended until the implementation solidifies. if (compilerOptions.noImplicitOverride + && !ambient && !(derivedDeclarationFlags & ModifierFlags.Abstract) && !(derivedDeclarationFlags & ModifierFlags.Override)) { - error(derived.valueDeclaration.name, Diagnostics.Class_member_0_must_be_marked_override_when_noImplicitOverride_is_enabled_1, - symbolToString(derived), "inherited from " + typeToString(baseType)); + error(derived.valueDeclaration.name, + Diagnostics.Class_member_0_must_be_marked_override_when_noImplicitOverride_is_enabled_augmented_from_Object_1, + symbolToString(derived), + typeToString(baseType)); } continue; @@ -18541,7 +18559,7 @@ namespace ts { } } - checkImplicitPropertyMemberOverrides(type, onlyInDerived); + checkAugmentedPropertyMemberOverrides(type, onlyInDerived); } function isAccessor(kind: SyntaxKind): boolean { @@ -21030,9 +21048,6 @@ namespace ts { else if (flags & ModifierFlags.Async) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "async"); } - else if (flags & ModifierFlags.Override) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "override"); - } else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, text); } @@ -21044,6 +21059,14 @@ namespace ts { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "abstract"); } } + else if (flags & ModifierFlags.Override) { + if (modifier.kind === SyntaxKind.PrivateKeyword) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, text, "override"); + } + else { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "override"); + } + } flags |= modifierToFlag(modifier.kind); break; @@ -21066,9 +21089,6 @@ namespace ts { else if (flags & ModifierFlags.Abstract) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); } - else if (flags & ModifierFlags.Override) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "override"); - } flags |= ModifierFlags.Static; lastStatic = modifier; break; @@ -21131,20 +21151,23 @@ namespace ts { if (flags & ModifierFlags.Abstract) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "abstract"); } - if (node.kind !== SyntaxKind.ClassDeclaration) { + else if (node.kind !== SyntaxKind.ClassDeclaration) { if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.GetAccessor && node.kind !== SyntaxKind.SetAccessor) { - return grammarErrorOnNode(modifier, Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration); + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_can_only_appear_on_a_class_method_or_property_declaration, "abstract"); } - if (!(node.parent.kind === SyntaxKind.ClassDeclaration && getModifierFlags(node.parent) & ModifierFlags.Abstract)) { + else if (!(node.parent.kind === SyntaxKind.ClassDeclaration && getModifierFlags(node.parent) & ModifierFlags.Abstract)) { return grammarErrorOnNode(modifier, Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class); } - if (flags & ModifierFlags.Static) { + else if (flags & ModifierFlags.Override) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "override", "abstract"); + } + else if (flags & ModifierFlags.Static) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); } - if (flags & ModifierFlags.Private) { + else if (flags & ModifierFlags.Private) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "abstract"); } } @@ -21157,17 +21180,33 @@ namespace ts { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "override"); } else if (flags & ModifierFlags.Static) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "override"); + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "static"); } - else if (flags & ModifierFlags.Private) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "override"); + else if (flags & ModifierFlags.Async) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "async"); + } + else if (flags & ModifierFlags.Readonly) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "readonly"); } else if (flags & ModifierFlags.Abstract) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "abstract", "override"); } + else if (flags & ModifierFlags.Private) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "override"); + } + else if (node.kind === SyntaxKind.Parameter) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "override"); + } else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, "override"); } + else if (node.kind !== SyntaxKind.MethodDeclaration && + node.kind !== SyntaxKind.PropertyDeclaration && + node.kind !== SyntaxKind.GetAccessor && + node.kind !== SyntaxKind.SetAccessor) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_can_only_appear_on_a_class_method_or_property_declaration, "override"); + } + flags |= ModifierFlags.Override; break; @@ -21191,7 +21230,7 @@ namespace ts { if (flags & ModifierFlags.Static) { return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static"); } - if (flags & ModifierFlags.Abstract) { + else if (flags & ModifierFlags.Abstract) { return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract"); } else if (flags & ModifierFlags.Async) { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 78843c58b74bd..af950ac8102bd 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -717,9 +717,6 @@ namespace ts { } function emitClassMemberDeclarationFlags(flags: ModifierFlags) { - if (flags & ModifierFlags.Override) { - write("override "); - } if (flags & ModifierFlags.Private) { write("private "); } @@ -730,6 +727,9 @@ namespace ts { if (flags & ModifierFlags.Static) { write("static "); } + if (flags & ModifierFlags.Override) { + write("override "); + } if (flags & ModifierFlags.Readonly) { write("readonly "); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 857733db7397e..9beda840cd2d1 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -767,7 +767,7 @@ "category": "Error", "code": 1241 }, - "'abstract' modifier can only appear on a class, method, or property declaration.": { + "'{0}' modifier can only appear on a class, method, or property declaration.": { "category": "Error", "code": 1242 }, @@ -3291,21 +3291,25 @@ "category": "Error", "code": 90030 }, - "Class member '{0}' was marked 'override', but no matching definition was found in any supertype of '{1}'": { + "Class member '{0}' was marked 'override', but no matching declaration was found in any supertype of '{1}'": { "category": "Error", "code": 90032 }, - "Class member '{0}' must be marked 'override' when noImplicitOverride is enabled ({1})": { + "Class member '{0}' must be marked 'override' when noImplicitOverride is enabled (inherited from {1})": { "category": "Error", "code": 90033 }, + "Class member '{0}' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.{1})": { + "category": "Error", + "code": 90034 + }, "override modifier cannot be used with an optional property declaration": { "category": "Error", - "code": 90034 + "code": 90035 }, "All declarations of an override method must be consecutive.": { "category": "Error", - "code": 90035 + "code": 90036 }, "Octal literal types must use ES2015 syntax. Use the syntax '{0}'.": { "category": "Error", diff --git a/tests/baselines/reference/noImplicitOverride.errors.txt b/tests/baselines/reference/noImplicitOverride.errors.txt index 8872952c500b5..4296d22cd732f 100644 --- a/tests/baselines/reference/noImplicitOverride.errors.txt +++ b/tests/baselines/reference/noImplicitOverride.errors.txt @@ -1,12 +1,13 @@ -tests/cases/compiler/noImplicitOverride.ts(10,5): error TS90033: Class member 'toString' must be marked 'override' when noImplicitOverride is enabled (inherited from Object) -tests/cases/compiler/noImplicitOverride.ts(11,5): error TS90033: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (inherited from Object) -tests/cases/compiler/noImplicitOverride.ts(17,5): error TS90033: Class member 'toString' must be marked 'override' when noImplicitOverride is enabled (masks Object.toString) -tests/cases/compiler/noImplicitOverride.ts(18,5): error TS90033: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (masks Object.hasOwnProperty) -tests/cases/compiler/noImplicitOverride.ts(24,5): error TS90033: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (masks Object.hasOwnProperty). The override declaration ((prop: string) => number) also has a different type signature than the original ((v: string) => boolean) -tests/cases/compiler/noImplicitOverride.ts(30,12): error TS90033: Class member 'userId' must be marked 'override' when noImplicitOverride is enabled (inherited from Base) -tests/cases/compiler/noImplicitOverride.ts(34,9): error TS90033: Class member 'name' must be marked 'override' when noImplicitOverride is enabled (inherited from Base) -tests/cases/compiler/noImplicitOverride.ts(42,5): error TS1070: 'override' modifier cannot appear on a type member. -tests/cases/compiler/noImplicitOverride.ts(51,29): error TS90033: Class member 'userId' must be marked 'override' when noImplicitOverride is enabled (inherited from Base) +tests/cases/compiler/noImplicitOverride.ts(11,5): error TS90034: Class member 'toString' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.Object) +tests/cases/compiler/noImplicitOverride.ts(12,5): error TS90034: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.Object) +tests/cases/compiler/noImplicitOverride.ts(18,5): error TS90034: Class member 'toString' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.toString) +tests/cases/compiler/noImplicitOverride.ts(19,5): error TS90034: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.hasOwnProperty) +tests/cases/compiler/noImplicitOverride.ts(25,5): error TS2322: Type '(prop: string) => number' is not assignable to type '(v: string) => boolean'. + Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.hasOwnProperty) +tests/cases/compiler/noImplicitOverride.ts(31,12): error TS90034: Class member 'userId' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.Base) +tests/cases/compiler/noImplicitOverride.ts(35,9): error TS90034: Class member 'name' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.Base) +tests/cases/compiler/noImplicitOverride.ts(43,5): error TS1070: 'override' modifier cannot appear on a type member. +tests/cases/compiler/noImplicitOverride.ts(52,29): error TS90034: Class member 'userId' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.Base) ==== tests/cases/compiler/noImplicitOverride.ts (9 errors) ==== @@ -15,27 +16,28 @@ tests/cases/compiler/noImplicitOverride.ts(51,29): error TS90033: Class member ' get name(): string { return 'Base'; } + getMeaningOfLife(): number { return 42; } public userId: number = 1; } class RejectWhenOverrideMissingOnInheritedMethod extends Object { toString(): string { return 'foo'; }; ~~~~~~~~ -!!! error TS90033: Class member 'toString' must be marked 'override' when noImplicitOverride is enabled (inherited from Object) +!!! error TS90034: Class member 'toString' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.Object) hasOwnProperty(prop: string): boolean { ~~~~~~~~~~~~~~ -!!! error TS90033: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (inherited from Object) +!!! error TS90034: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.Object) return super.hasOwnProperty(prop); } } - class RejectWhenOverrideMissingOnMethodThatMasksObjectTypeMember { + class RejectWhenOverrideMissingOnAugmentedProperty { toString(): string { return 'foo'; }; ~~~~~~~~ -!!! error TS90033: Class member 'toString' must be marked 'override' when noImplicitOverride is enabled (masks Object.toString) +!!! error TS90034: Class member 'toString' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.toString) hasOwnProperty(prop: string): boolean { ~~~~~~~~~~~~~~ -!!! error TS90033: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (masks Object.hasOwnProperty) +!!! error TS90034: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.hasOwnProperty) return false; } } @@ -43,7 +45,8 @@ tests/cases/compiler/noImplicitOverride.ts(51,29): error TS90033: Class member ' class RejectWhenOverrideTypeMismatchOnMethodThatMasksObjectTypeMember { hasOwnProperty(prop: string): number { ~~~~~~~~~~~~~~ -!!! error TS90033: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (masks Object.hasOwnProperty). The override declaration ((prop: string) => number) also has a different type signature than the original ((v: string) => boolean) +!!! error TS2322: Type '(prop: string) => number' is not assignable to type '(v: string) => boolean'. +!!! error TS2322: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.hasOwnProperty) return -1; } } @@ -51,13 +54,13 @@ tests/cases/compiler/noImplicitOverride.ts(51,29): error TS90033: Class member ' class RejectWhenOverrideMissingOnInheritedProperty extends Base { public userId = 2; ~~~~~~ -!!! error TS90033: Class member 'userId' must be marked 'override' when noImplicitOverride is enabled (inherited from Base) +!!! error TS90034: Class member 'userId' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.Base) } class RejectWhenOverrideMissingOnInheritedAccessor extends Base { get name(): string { return 'foo'; }; ~~~~ -!!! error TS90033: Class member 'name' must be marked 'override' when noImplicitOverride is enabled (inherited from Base) +!!! error TS90034: Class member 'name' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.Base) } interface Shape { @@ -78,6 +81,6 @@ tests/cases/compiler/noImplicitOverride.ts(51,29): error TS90033: Class member ' class FIXME_AcceptWhenOverrideSpecifiedByJSDocAnnotation extends Base { /** @override */ public userId: number = 2; ~~~~~~ -!!! error TS90033: Class member 'userId' must be marked 'override' when noImplicitOverride is enabled (inherited from Base) +!!! error TS90034: Class member 'userId' must be marked 'override' when noImplicitOverride is enabled (augmented from Object.Base) } \ No newline at end of file diff --git a/tests/baselines/reference/noImplicitOverride.js b/tests/baselines/reference/noImplicitOverride.js index ca1cee5d662e6..dba3cecbe7a44 100644 --- a/tests/baselines/reference/noImplicitOverride.js +++ b/tests/baselines/reference/noImplicitOverride.js @@ -4,6 +4,7 @@ class Base { get name(): string { return 'Base'; } + getMeaningOfLife(): number { return 42; } public userId: number = 1; } @@ -14,7 +15,7 @@ class RejectWhenOverrideMissingOnInheritedMethod extends Object { } } -class RejectWhenOverrideMissingOnMethodThatMasksObjectTypeMember { +class RejectWhenOverrideMissingOnAugmentedProperty { toString(): string { return 'foo'; }; hasOwnProperty(prop: string): boolean { return false; @@ -54,11 +55,16 @@ class FIXME_AcceptWhenOverrideSpecifiedByJSDocAnnotation extends Base { //// [noImplicitOverride.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 __()); -}; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); var Base = (function () { function Base() { this.userId = 1; @@ -70,12 +76,13 @@ var Base = (function () { enumerable: true, configurable: true }); + Base.prototype.getMeaningOfLife = function () { return 42; }; return Base; }()); var RejectWhenOverrideMissingOnInheritedMethod = (function (_super) { __extends(RejectWhenOverrideMissingOnInheritedMethod, _super); function RejectWhenOverrideMissingOnInheritedMethod() { - return _super.apply(this, arguments) || this; + return _super !== null && _super.apply(this, arguments) || this; } RejectWhenOverrideMissingOnInheritedMethod.prototype.toString = function () { return 'foo'; }; ; @@ -84,15 +91,15 @@ var RejectWhenOverrideMissingOnInheritedMethod = (function (_super) { }; return RejectWhenOverrideMissingOnInheritedMethod; }(Object)); -var RejectWhenOverrideMissingOnMethodThatMasksObjectTypeMember = (function () { - function RejectWhenOverrideMissingOnMethodThatMasksObjectTypeMember() { +var RejectWhenOverrideMissingOnAugmentedProperty = (function () { + function RejectWhenOverrideMissingOnAugmentedProperty() { } - RejectWhenOverrideMissingOnMethodThatMasksObjectTypeMember.prototype.toString = function () { return 'foo'; }; + RejectWhenOverrideMissingOnAugmentedProperty.prototype.toString = function () { return 'foo'; }; ; - RejectWhenOverrideMissingOnMethodThatMasksObjectTypeMember.prototype.hasOwnProperty = function (prop) { + RejectWhenOverrideMissingOnAugmentedProperty.prototype.hasOwnProperty = function (prop) { return false; }; - return RejectWhenOverrideMissingOnMethodThatMasksObjectTypeMember; + return RejectWhenOverrideMissingOnAugmentedProperty; }()); var RejectWhenOverrideTypeMismatchOnMethodThatMasksObjectTypeMember = (function () { function RejectWhenOverrideTypeMismatchOnMethodThatMasksObjectTypeMember() { @@ -105,7 +112,7 @@ var RejectWhenOverrideTypeMismatchOnMethodThatMasksObjectTypeMember = (function var RejectWhenOverrideMissingOnInheritedProperty = (function (_super) { __extends(RejectWhenOverrideMissingOnInheritedProperty, _super); function RejectWhenOverrideMissingOnInheritedProperty() { - var _this = _super.apply(this, arguments) || this; + var _this = _super !== null && _super.apply(this, arguments) || this; _this.userId = 2; return _this; } @@ -114,7 +121,7 @@ var RejectWhenOverrideMissingOnInheritedProperty = (function (_super) { var RejectWhenOverrideMissingOnInheritedAccessor = (function (_super) { __extends(RejectWhenOverrideMissingOnInheritedAccessor, _super); function RejectWhenOverrideMissingOnInheritedAccessor() { - return _super.apply(this, arguments) || this; + return _super !== null && _super.apply(this, arguments) || this; } Object.defineProperty(RejectWhenOverrideMissingOnInheritedAccessor.prototype, "name", { get: function () { return 'foo'; }, @@ -127,7 +134,7 @@ var RejectWhenOverrideMissingOnInheritedAccessor = (function (_super) { var FIXME_AcceptWhenOverrideSpecifiedByJSDocAnnotation = (function (_super) { __extends(FIXME_AcceptWhenOverrideSpecifiedByJSDocAnnotation, _super); function FIXME_AcceptWhenOverrideSpecifiedByJSDocAnnotation() { - var _this = _super.apply(this, arguments) || this; + var _this = _super !== null && _super.apply(this, arguments) || this; /** @override */ _this.userId = 2; return _this; } diff --git a/tests/baselines/reference/overrideKeyword.errors.txt b/tests/baselines/reference/overrideKeyword.errors.txt deleted file mode 100644 index 55a852ae9eb98..0000000000000 --- a/tests/baselines/reference/overrideKeyword.errors.txt +++ /dev/null @@ -1,147 +0,0 @@ -tests/cases/compiler/overrideKeyword.ts(4,12): error TS90033: Class member 'toString' must be marked 'override' when noImplicitOverride is enabled (masks Object.toString) -tests/cases/compiler/overrideKeyword.ts(14,5): error TS90033: Class member 'toStringAbstract' must be marked 'override' when noImplicitOverride is enabled (inherited from AbstractBase) -tests/cases/compiler/overrideKeyword.ts(25,5): error TS90034: override modifier cannot be used with an optional property declaration -tests/cases/compiler/overrideKeyword.ts(29,14): error TS1243: 'abstract' modifier cannot be used with 'override' modifier. -tests/cases/compiler/overrideKeyword.ts(33,14): error TS1243: 'static' modifier cannot be used with 'override' modifier. -tests/cases/compiler/overrideKeyword.ts(36,7): error TS2415: Class 'RejectWhenAttemptToOverridePrivateMethod' incorrectly extends base class 'Base'. - Types have separate declarations of a private property 'toStringPrivate'. -tests/cases/compiler/overrideKeyword.ts(37,13): error TS1243: 'private' modifier cannot be used with 'override' modifier. -tests/cases/compiler/overrideKeyword.ts(41,21): error TS1030: 'override' modifier already seen. -tests/cases/compiler/overrideKeyword.ts(45,14): error TS1029: 'public' modifier must precede 'override' modifier. -tests/cases/compiler/overrideKeyword.ts(49,21): error TS90032: Class member 'iDontExist' was marked 'override', but no matching definition was found in any supertype of 'RejectWhenOverrideMarkedOnNonInheritedMember' -tests/cases/compiler/overrideKeyword.ts(52,7): error TS2415: Class 'RejectWhenOverrideHasMismatchedType' incorrectly extends base class 'Base'. - Types of property 'getMeaningOfLife' are incompatible. - Type '() => string' is not assignable to type '() => number'. - Type 'string' is not assignable to type 'number'. -tests/cases/compiler/overrideKeyword.ts(57,18): error TS2699: Accessors must both be override or non-override. -tests/cases/compiler/overrideKeyword.ts(60,9): error TS2699: Accessors must both be override or non-override. -tests/cases/compiler/overrideKeyword.ts(67,14): error TS90033: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (masks Object.hasOwnProperty) -tests/cases/compiler/overrideKeyword.ts(71,12): error TS90033: Class member 'getMeaningOfLife' must be marked 'override' when noImplicitOverride is enabled (inherited from Base) -tests/cases/compiler/overrideKeyword.ts(75,14): error TS90033: Class member 'propertyIsEnumerable' must be marked 'override' when noImplicitOverride is enabled (masks Object.propertyIsEnumerable) - - -==== tests/cases/compiler/overrideKeyword.ts (16 errors) ==== - - abstract class AbstractBase { - static toStringStatic(): string { return 'static member'; } - public toString(): string { return 'instance member'; }; - ~~~~~~~~ -!!! error TS90033: Class member 'toString' must be marked 'override' when noImplicitOverride is enabled (masks Object.toString) - abstract toStringAbstract(): string; - private toStringPrivate(): string { return 'private member'; } - getMeaningOfLife(): number { return 42; } - public wasDisposed?: boolean; - } - - class Base extends AbstractBase { - private name_: string; - - toStringAbstract(): string { return 'implementation of abstract member'; }; - ~~~~~~~~~~~~~~~~ -!!! error TS90033: Class member 'toStringAbstract' must be marked 'override' when noImplicitOverride is enabled (inherited from AbstractBase) - - get name() { - return this.name_; - } - - set name(name: string) { - this.name_ = name; - } - - // override cannot be used with optional property. - public override wasDisposed?: boolean; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS90034: override modifier cannot be used with an optional property declaration - } - - abstract class RejectWhenAttemptToOverrideAbstractMethod extends AbstractBase { - abstract override toStringAbstract(): string; - ~~~~~~~~ -!!! error TS1243: 'abstract' modifier cannot be used with 'override' modifier. - } - - class RejectWhenAttemptToOverrideStaticMethod extends Base { - override static toStringStatic() { return ''; }; - ~~~~~~ -!!! error TS1243: 'static' modifier cannot be used with 'override' modifier. - } - - class RejectWhenAttemptToOverridePrivateMethod extends Base { - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2415: Class 'RejectWhenAttemptToOverridePrivateMethod' incorrectly extends base class 'Base'. -!!! error TS2415: Types have separate declarations of a private property 'toStringPrivate'. - private override toStringPrivate() { return ''; }; - ~~~~~~~~ -!!! error TS1243: 'private' modifier cannot be used with 'override' modifier. - } - - class RejectWhenOverrideIsRepeated extends Base { - public override override toString() { return ''; }; - ~~~~~~~~ -!!! error TS1030: 'override' modifier already seen. - } - - class RejectWhenOverridePrecedesAccessModifier extends Base { - override public toString() { return ''; }; - ~~~~~~ -!!! error TS1029: 'public' modifier must precede 'override' modifier. - } - - class RejectWhenOverrideMarkedOnNonInheritedMember extends Base { - public override iDontExist() { return ''; }; - ~~~~~~~~~~ -!!! error TS90032: Class member 'iDontExist' was marked 'override', but no matching definition was found in any supertype of 'RejectWhenOverrideMarkedOnNonInheritedMember' - } - - class RejectWhenOverrideHasMismatchedType extends Base { - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2415: Class 'RejectWhenOverrideHasMismatchedType' incorrectly extends base class 'Base'. -!!! error TS2415: Types of property 'getMeaningOfLife' are incompatible. -!!! error TS2415: Type '() => string' is not assignable to type '() => number'. -!!! error TS2415: Type 'string' is not assignable to type 'number'. - override getMeaningOfLife(): string { return 'forty-two'; }; - } - - class RejectWhenAccessorNotBothOverride extends Base { - override get name() { - ~~~~ -!!! error TS2699: Accessors must both be override or non-override. - return 'hardcoded value'; - } - set name(n: string) { - ~~~~ -!!! error TS2699: Accessors must both be override or non-override. - } - } - - /* @mhegazy: is this an appropriate test for consecutive declarations? */ - class RejectWhenOverrideDeclarationsAreNotConsecutive extends Base { - - override hasOwnProperty(prop: string): boolean { - ~~~~~~~~~~~~~~ -!!! error TS90033: Class member 'hasOwnProperty' must be marked 'override' when noImplicitOverride is enabled (masks Object.hasOwnProperty) - return super.hasOwnProperty(prop); - } - - public getMeaningOfLife(): number { - ~~~~~~~~~~~~~~~~ -!!! error TS90033: Class member 'getMeaningOfLife' must be marked 'override' when noImplicitOverride is enabled (inherited from Base) - return 42; - } - - override propertyIsEnumerable(prop: string): boolean { - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS90033: Class member 'propertyIsEnumerable' must be marked 'override' when noImplicitOverride is enabled (masks Object.propertyIsEnumerable) - return super.propertyIsEnumerable(prop); - } - - } - - class AcceptWhenOverrideFollowsAccessModifier extends Base { - public override toString() { return ''; }; - } - - class AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass extends Base { - public override getMeaningOfLife(): number { return 12; }; - } - \ No newline at end of file diff --git a/tests/baselines/reference/overrideKeyword.js b/tests/baselines/reference/overrideKeyword.js deleted file mode 100644 index 84621b2bbd143..0000000000000 --- a/tests/baselines/reference/overrideKeyword.js +++ /dev/null @@ -1,237 +0,0 @@ -//// [overrideKeyword.ts] - -abstract class AbstractBase { - static toStringStatic(): string { return 'static member'; } - public toString(): string { return 'instance member'; }; - abstract toStringAbstract(): string; - private toStringPrivate(): string { return 'private member'; } - getMeaningOfLife(): number { return 42; } - public wasDisposed?: boolean; -} - -class Base extends AbstractBase { - private name_: string; - - toStringAbstract(): string { return 'implementation of abstract member'; }; - - get name() { - return this.name_; - } - - set name(name: string) { - this.name_ = name; - } - - // override cannot be used with optional property. - public override wasDisposed?: boolean; -} - -abstract class RejectWhenAttemptToOverrideAbstractMethod extends AbstractBase { - abstract override toStringAbstract(): string; -} - -class RejectWhenAttemptToOverrideStaticMethod extends Base { - override static toStringStatic() { return ''; }; -} - -class RejectWhenAttemptToOverridePrivateMethod extends Base { - private override toStringPrivate() { return ''; }; -} - -class RejectWhenOverrideIsRepeated extends Base { - public override override toString() { return ''; }; -} - -class RejectWhenOverridePrecedesAccessModifier extends Base { - override public toString() { return ''; }; -} - -class RejectWhenOverrideMarkedOnNonInheritedMember extends Base { - public override iDontExist() { return ''; }; -} - -class RejectWhenOverrideHasMismatchedType extends Base { - override getMeaningOfLife(): string { return 'forty-two'; }; -} - -class RejectWhenAccessorNotBothOverride extends Base { - override get name() { - return 'hardcoded value'; - } - set name(n: string) { - } -} - -/* @mhegazy: is this an appropriate test for consecutive declarations? */ -class RejectWhenOverrideDeclarationsAreNotConsecutive extends Base { - - override hasOwnProperty(prop: string): boolean { - return super.hasOwnProperty(prop); - } - - public getMeaningOfLife(): number { - return 42; - } - - override propertyIsEnumerable(prop: string): boolean { - return super.propertyIsEnumerable(prop); - } - -} - -class AcceptWhenOverrideFollowsAccessModifier extends Base { - public override toString() { return ''; }; -} - -class AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass extends Base { - public override getMeaningOfLife(): number { return 12; }; -} - - -//// [overrideKeyword.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 __()); -}; -var AbstractBase = (function () { - function AbstractBase() { - } - AbstractBase.toStringStatic = function () { return 'static member'; }; - AbstractBase.prototype.toString = function () { return 'instance member'; }; - ; - AbstractBase.prototype.toStringPrivate = function () { return 'private member'; }; - AbstractBase.prototype.getMeaningOfLife = function () { return 42; }; - return AbstractBase; -}()); -var Base = (function (_super) { - __extends(Base, _super); - function Base() { - return _super.apply(this, arguments) || this; - } - Base.prototype.toStringAbstract = function () { return 'implementation of abstract member'; }; - ; - Object.defineProperty(Base.prototype, "name", { - get: function () { - return this.name_; - }, - set: function (name) { - this.name_ = name; - }, - enumerable: true, - configurable: true - }); - return Base; -}(AbstractBase)); -var RejectWhenAttemptToOverrideAbstractMethod = (function (_super) { - __extends(RejectWhenAttemptToOverrideAbstractMethod, _super); - function RejectWhenAttemptToOverrideAbstractMethod() { - return _super.apply(this, arguments) || this; - } - return RejectWhenAttemptToOverrideAbstractMethod; -}(AbstractBase)); -var RejectWhenAttemptToOverrideStaticMethod = (function (_super) { - __extends(RejectWhenAttemptToOverrideStaticMethod, _super); - function RejectWhenAttemptToOverrideStaticMethod() { - return _super.apply(this, arguments) || this; - } - RejectWhenAttemptToOverrideStaticMethod.toStringStatic = function () { return ''; }; - ; - return RejectWhenAttemptToOverrideStaticMethod; -}(Base)); -var RejectWhenAttemptToOverridePrivateMethod = (function (_super) { - __extends(RejectWhenAttemptToOverridePrivateMethod, _super); - function RejectWhenAttemptToOverridePrivateMethod() { - return _super.apply(this, arguments) || this; - } - RejectWhenAttemptToOverridePrivateMethod.prototype.toStringPrivate = function () { return ''; }; - ; - return RejectWhenAttemptToOverridePrivateMethod; -}(Base)); -var RejectWhenOverrideIsRepeated = (function (_super) { - __extends(RejectWhenOverrideIsRepeated, _super); - function RejectWhenOverrideIsRepeated() { - return _super.apply(this, arguments) || this; - } - RejectWhenOverrideIsRepeated.prototype.toString = function () { return ''; }; - ; - return RejectWhenOverrideIsRepeated; -}(Base)); -var RejectWhenOverridePrecedesAccessModifier = (function (_super) { - __extends(RejectWhenOverridePrecedesAccessModifier, _super); - function RejectWhenOverridePrecedesAccessModifier() { - return _super.apply(this, arguments) || this; - } - RejectWhenOverridePrecedesAccessModifier.prototype.toString = function () { return ''; }; - ; - return RejectWhenOverridePrecedesAccessModifier; -}(Base)); -var RejectWhenOverrideMarkedOnNonInheritedMember = (function (_super) { - __extends(RejectWhenOverrideMarkedOnNonInheritedMember, _super); - function RejectWhenOverrideMarkedOnNonInheritedMember() { - return _super.apply(this, arguments) || this; - } - RejectWhenOverrideMarkedOnNonInheritedMember.prototype.iDontExist = function () { return ''; }; - ; - return RejectWhenOverrideMarkedOnNonInheritedMember; -}(Base)); -var RejectWhenOverrideHasMismatchedType = (function (_super) { - __extends(RejectWhenOverrideHasMismatchedType, _super); - function RejectWhenOverrideHasMismatchedType() { - return _super.apply(this, arguments) || this; - } - RejectWhenOverrideHasMismatchedType.prototype.getMeaningOfLife = function () { return 'forty-two'; }; - ; - return RejectWhenOverrideHasMismatchedType; -}(Base)); -var RejectWhenAccessorNotBothOverride = (function (_super) { - __extends(RejectWhenAccessorNotBothOverride, _super); - function RejectWhenAccessorNotBothOverride() { - return _super.apply(this, arguments) || this; - } - Object.defineProperty(RejectWhenAccessorNotBothOverride.prototype, "name", { - get: function () { - return 'hardcoded value'; - }, - set: function (n) { - }, - enumerable: true, - configurable: true - }); - return RejectWhenAccessorNotBothOverride; -}(Base)); -/* @mhegazy: is this an appropriate test for consecutive declarations? */ -var RejectWhenOverrideDeclarationsAreNotConsecutive = (function (_super) { - __extends(RejectWhenOverrideDeclarationsAreNotConsecutive, _super); - function RejectWhenOverrideDeclarationsAreNotConsecutive() { - return _super.apply(this, arguments) || this; - } - RejectWhenOverrideDeclarationsAreNotConsecutive.prototype.hasOwnProperty = function (prop) { - return _super.prototype.hasOwnProperty.call(this, prop); - }; - RejectWhenOverrideDeclarationsAreNotConsecutive.prototype.getMeaningOfLife = function () { - return 42; - }; - RejectWhenOverrideDeclarationsAreNotConsecutive.prototype.propertyIsEnumerable = function (prop) { - return _super.prototype.propertyIsEnumerable.call(this, prop); - }; - return RejectWhenOverrideDeclarationsAreNotConsecutive; -}(Base)); -var AcceptWhenOverrideFollowsAccessModifier = (function (_super) { - __extends(AcceptWhenOverrideFollowsAccessModifier, _super); - function AcceptWhenOverrideFollowsAccessModifier() { - return _super.apply(this, arguments) || this; - } - AcceptWhenOverrideFollowsAccessModifier.prototype.toString = function () { return ''; }; - ; - return AcceptWhenOverrideFollowsAccessModifier; -}(Base)); -var AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass = (function (_super) { - __extends(AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass, _super); - function AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass() { - return _super.apply(this, arguments) || this; - } - AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass.prototype.getMeaningOfLife = function () { return 12; }; - ; - return AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass; -}(Base)); diff --git a/tests/baselines/reference/overrideKeyword.symbols b/tests/baselines/reference/overrideKeyword.symbols deleted file mode 100644 index 310ce18f6f286..0000000000000 --- a/tests/baselines/reference/overrideKeyword.symbols +++ /dev/null @@ -1,17 +0,0 @@ -=== tests/cases/compiler/overrideKeyword.ts === -class Base { ->Base : Symbol(Base, Decl(overrideKeyword.ts, 0, 0)) - - public toString() { return "base"; }; ->toString : Symbol(Base.toString, Decl(overrideKeyword.ts, 0, 12)) -} - -class Derived extends Base { ->Derived : Symbol(Derived, Decl(overrideKeyword.ts, 2, 1)) ->Base : Symbol(Base, Decl(overrideKeyword.ts, 0, 0)) - - /** @override */ - public override toString() { return "derived"; }; ->toString : Symbol(Derived.toString, Decl(overrideKeyword.ts, 4, 28)) -} - diff --git a/tests/baselines/reference/overrideKeyword.types b/tests/baselines/reference/overrideKeyword.types deleted file mode 100644 index 9748e915a7ce4..0000000000000 --- a/tests/baselines/reference/overrideKeyword.types +++ /dev/null @@ -1,19 +0,0 @@ -=== tests/cases/compiler/overrideKeyword.ts === -class Base { ->Base : Base - - public toString() { return "base"; }; ->toString : () => string ->"base" : "base" -} - -class Derived extends Base { ->Derived : Derived ->Base : Base - - /** @override */ - public override toString() { return "derived"; }; ->toString : () => string ->"derived" : "derived" -} - diff --git a/tests/baselines/reference/overrideKeywordEs5.errors.txt b/tests/baselines/reference/overrideKeywordEs5.errors.txt new file mode 100644 index 0000000000000..7acba2cd39852 --- /dev/null +++ b/tests/baselines/reference/overrideKeywordEs5.errors.txt @@ -0,0 +1,197 @@ +tests/cases/compiler/overrideKeywordEs5.ts(29,72): error TS1029: 'public' modifier must precede 'override' modifier. +tests/cases/compiler/overrideKeywordEs5.ts(30,75): error TS1029: 'protected' modifier must precede 'override' modifier. +tests/cases/compiler/overrideKeywordEs5.ts(31,70): error TS1029: 'override' modifier must precede 'static' modifier. +tests/cases/compiler/overrideKeywordEs5.ts(33,74): error TS1029: 'override' modifier must precede 'readonly' modifier. +tests/cases/compiler/overrideKeywordEs5.ts(37,21): error TS1030: 'override' modifier already seen. +tests/cases/compiler/overrideKeywordEs5.ts(41,7): error TS2415: Class 'RejectWhenOverridePrivateMethod' incorrectly extends base class 'Base'. + Types have separate declarations of a private property 'toStringPrivate'. +tests/cases/compiler/overrideKeywordEs5.ts(42,13): error TS1243: 'private' modifier cannot be used with 'override' modifier. +tests/cases/compiler/overrideKeywordEs5.ts(43,14): error TS1243: 'private' modifier cannot be used with 'override' modifier. +tests/cases/compiler/overrideKeywordEs5.ts(48,14): error TS1243: 'abstract' modifier cannot be used with 'override' modifier. +tests/cases/compiler/overrideKeywordEs5.ts(49,14): error TS1243: 'override' modifier cannot be used with 'abstract' modifier. +tests/cases/compiler/overrideKeywordEs5.ts(64,7): error TS2417: Class static side 'typeof RejectWhenOverrideChangesAccessModifier' incorrectly extends base class static side 'typeof Base'. + Property 'toStringStatic' is protected in type 'typeof RejectWhenOverrideChangesAccessModifier' but public in type 'typeof Base'. +tests/cases/compiler/overrideKeywordEs5.ts(76,5): error TS90035: override modifier cannot be used with an optional property declaration +tests/cases/compiler/overrideKeywordEs5.ts(81,18): error TS2699: Accessors must both be override or non-override. +tests/cases/compiler/overrideKeywordEs5.ts(82,18): error TS2699: Accessors must both be override or non-override. +tests/cases/compiler/overrideKeywordEs5.ts(87,21): error TS90032: Class member 'iDontExist' was marked 'override', but no matching declaration was found in any supertype of 'RejectWhenOverrideMarkedOnNonInheritedMember' +tests/cases/compiler/overrideKeywordEs5.ts(92,7): error TS2415: Class 'RejectWhenOverrideHasMismatchedType' incorrectly extends base class 'Base'. + Types of property 'getMeaningOfLife' are incompatible. + Type '() => string' is not assignable to type '() => number'. + Type 'string' is not assignable to type 'number'. +tests/cases/compiler/overrideKeywordEs5.ts(98,21): error TS1090: 'override' modifier cannot appear on a parameter. +tests/cases/compiler/overrideKeywordEs5.ts(102,1): error TS1044: 'override' modifier cannot appear on a module or namespace element. +tests/cases/compiler/overrideKeywordEs5.ts(103,1): error TS1044: 'override' modifier cannot appear on a module or namespace element. +tests/cases/compiler/overrideKeywordEs5.ts(107,5): error TS1070: 'override' modifier cannot appear on a type member. + + +==== tests/cases/compiler/overrideKeywordEs5.ts (20 errors) ==== + + abstract class AbstractBase { + readonly id: string; + public wasDisposed?: boolean; + private name_: string; + get name() { return this.name_; } + set name(name: string) { this.name_ = name; } + + static toStringStatic(): string { return 'static'; } + public toStringPublic(): string { return 'public'; }; + protected toStringProtected(): string { return 'protected'; } + private toStringPrivate(): string { return 'private'; } + private toStringPrivate2(): string { return 'private2'; } + abstract toStringAbstract(): string; + abstract toStringAbstract2(): string; + + getMeaningOfLife(): number { return 42; } + } + + class Base extends AbstractBase { + override toStringAbstract(): string { return 'implemented'; } + override toStringAbstract2(): string { return 'implemented2'; } + } + + // The expected order of modifiers: + // + // [public | protected | private] [abstract | override] [static] [readonly | async] [get | set] identifier + // + class RejectWhenOverridePrecedesPublicModifier extends Base { override public toStringPublic() { return ''; }; } + ~~~~~~ +!!! error TS1029: 'public' modifier must precede 'override' modifier. + class RejectWhenOverridePrecedesProtectedModifier extends Base { override protected toStringProtected() { return ''; }; } + ~~~~~~~~~ +!!! error TS1029: 'protected' modifier must precede 'override' modifier. + class RejectWhenStaticPrecedesOverrideModifier extends Base { static override toStringStatic() { return ''; }; } + ~~~~~~~~ +!!! error TS1029: 'override' modifier must precede 'static' modifier. + class AcceptWhenOverrideFollowsAccessModifier extends Base { public override toStringPublic() { return ''; } } + class RejectWhenReadonlyPrecedesOverrideModifier extends Base { readonly override id: string; } + ~~~~~~~~ +!!! error TS1029: 'override' modifier must precede 'readonly' modifier. + + // Modifiers should never be repeated + class RejectWhenOverrideIsRepeated extends Base { + public override override toStringPublic() { return ''; } + ~~~~~~~~ +!!! error TS1030: 'override' modifier already seen. + } + + // You cannot override a private method + class RejectWhenOverridePrivateMethod extends Base { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2415: Class 'RejectWhenOverridePrivateMethod' incorrectly extends base class 'Base'. +!!! error TS2415: Types have separate declarations of a private property 'toStringPrivate'. + private override toStringPrivate() { return ''; } + ~~~~~~~~ +!!! error TS1243: 'private' modifier cannot be used with 'override' modifier. + override private toStringPrivate2() { return ''; } + ~~~~~~~ +!!! error TS1243: 'private' modifier cannot be used with 'override' modifier. + } + + // Override and abstract on methods are orthogonal, should never be used together + abstract class RejectWhenOverrideAbstractMethod extends AbstractBase { + abstract override toStringAbstract(): string; + ~~~~~~~~ +!!! error TS1243: 'abstract' modifier cannot be used with 'override' modifier. + override abstract toStringAbstract2(): string; + ~~~~~~~~ +!!! error TS1243: 'override' modifier cannot be used with 'abstract' modifier. + } + + // Acceptable to provide an override implementation in an abstract class however + abstract class AcceptWhenOverrideInAbstractClass extends AbstractBase { + override toStringAbstract(): string { return 'implemented in abstract class'; } + } + + // Override checks are allowed on static methods + class AcceptWhenOverrideStaticMethod extends Base { + override static toStringStatic() { return 'static'; } + } + + // Compiler already checks for access modifier narrowing, + // override does not alter these semantics. + class RejectWhenOverrideChangesAccessModifier extends Base { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2417: Class static side 'typeof RejectWhenOverrideChangesAccessModifier' incorrectly extends base class static side 'typeof Base'. +!!! error TS2417: Property 'toStringStatic' is protected in type 'typeof RejectWhenOverrideChangesAccessModifier' but public in type 'typeof Base'. + protected override static toStringStatic() { return 'member is now protected'; } + } + + // Compiler should be able to traverse multiple levels of inheritance + // to assess for overriden members (already does this). + class AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass extends Base { + override getMeaningOfLife(): number { return 12; } + } + + // Override cannot be used with optional property. + class RejectWhenOverrideOptionalProperty extends Base { + public override wasDisposed?: boolean; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS90035: override modifier cannot be used with an optional property declaration + } + + // If one accessor is marked override, they both should be. + class RejectWhenAccessorNotBothOverride extends Base { + override get name() { return ''; } + ~~~~ +!!! error TS2699: Accessors must both be override or non-override. + /* */ set name(n: string) {} + ~~~~ +!!! error TS2699: Accessors must both be override or non-override. + } + + // Compiler should detect when override member is not inherited or augmented + class RejectWhenOverrideMarkedOnNonInheritedMember extends Base { + public override iDontExist() { return ''; } + ~~~~~~~~~~ +!!! error TS90032: Class member 'iDontExist' was marked 'override', but no matching declaration was found in any supertype of 'RejectWhenOverrideMarkedOnNonInheritedMember' + } + + // Compiler already detects overriden assignability mismatches, + // override keyword does not change these semantics + class RejectWhenOverrideHasMismatchedType extends Base { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2415: Class 'RejectWhenOverrideHasMismatchedType' incorrectly extends base class 'Base'. +!!! error TS2415: Types of property 'getMeaningOfLife' are incompatible. +!!! error TS2415: Type '() => string' is not assignable to type '() => number'. +!!! error TS2415: Type 'string' is not assignable to type 'number'. + override getMeaningOfLife(): string { return 'the meaning of life is a number, not a string'; } + } + + // Override is not be used on parameters + class RejectWhenOverrideIsOnAParameter { + public sayHello(override name: string) { return 'hi'; } + ~~~~~~~~ +!!! error TS1090: 'override' modifier cannot appear on a parameter. + } + + // Override is not used on class... + override class RejectWhenOverrideIsOnClassDeclaration { public sayHello(name: string) { return ''; } } + ~~~~~~~~ +!!! error TS1044: 'override' modifier cannot appear on a module or namespace element. + override interface RejectWhenOverrideIsOnInterfaceDeclaration { sayHello(name: string); } + ~~~~~~~~ +!!! error TS1044: 'override' modifier cannot appear on a module or namespace element. + + //... or interface declarations + interface RejectWhenOverrideInAnInterface { + override sayHello(name: string); + ~~~~~~~~ +!!! error TS1070: 'override' modifier cannot appear on a type member. + } + + /* @mhegazy: is this an appropriate test for consecutive declarations? */ + class RejectWhenOverrideDeclarationsAreNotConsecutive extends Base { + override hasOwnProperty(prop: string): boolean { + return super.hasOwnProperty(prop); + } + + public getMeaningOfLife(): number { + return 42; + } + + override propertyIsEnumerable(prop: string): boolean { + return super.propertyIsEnumerable(prop); + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/overrideKeywordEs5.js b/tests/baselines/reference/overrideKeywordEs5.js new file mode 100644 index 0000000000000..c676203528323 --- /dev/null +++ b/tests/baselines/reference/overrideKeywordEs5.js @@ -0,0 +1,435 @@ +//// [overrideKeywordEs5.ts] + +abstract class AbstractBase { + readonly id: string; + public wasDisposed?: boolean; + private name_: string; + get name() { return this.name_; } + set name(name: string) { this.name_ = name; } + + static toStringStatic(): string { return 'static'; } + public toStringPublic(): string { return 'public'; }; + protected toStringProtected(): string { return 'protected'; } + private toStringPrivate(): string { return 'private'; } + private toStringPrivate2(): string { return 'private2'; } + abstract toStringAbstract(): string; + abstract toStringAbstract2(): string; + + getMeaningOfLife(): number { return 42; } +} + +class Base extends AbstractBase { + override toStringAbstract(): string { return 'implemented'; } + override toStringAbstract2(): string { return 'implemented2'; } +} + +// The expected order of modifiers: +// +// [public | protected | private] [abstract | override] [static] [readonly | async] [get | set] identifier +// +class RejectWhenOverridePrecedesPublicModifier extends Base { override public toStringPublic() { return ''; }; } +class RejectWhenOverridePrecedesProtectedModifier extends Base { override protected toStringProtected() { return ''; }; } +class RejectWhenStaticPrecedesOverrideModifier extends Base { static override toStringStatic() { return ''; }; } +class AcceptWhenOverrideFollowsAccessModifier extends Base { public override toStringPublic() { return ''; } } +class RejectWhenReadonlyPrecedesOverrideModifier extends Base { readonly override id: string; } + +// Modifiers should never be repeated +class RejectWhenOverrideIsRepeated extends Base { + public override override toStringPublic() { return ''; } +} + +// You cannot override a private method +class RejectWhenOverridePrivateMethod extends Base { + private override toStringPrivate() { return ''; } + override private toStringPrivate2() { return ''; } +} + +// Override and abstract on methods are orthogonal, should never be used together +abstract class RejectWhenOverrideAbstractMethod extends AbstractBase { + abstract override toStringAbstract(): string; + override abstract toStringAbstract2(): string; +} + +// Acceptable to provide an override implementation in an abstract class however +abstract class AcceptWhenOverrideInAbstractClass extends AbstractBase { + override toStringAbstract(): string { return 'implemented in abstract class'; } +} + +// Override checks are allowed on static methods +class AcceptWhenOverrideStaticMethod extends Base { + override static toStringStatic() { return 'static'; } +} + +// Compiler already checks for access modifier narrowing, +// override does not alter these semantics. +class RejectWhenOverrideChangesAccessModifier extends Base { + protected override static toStringStatic() { return 'member is now protected'; } +} + +// Compiler should be able to traverse multiple levels of inheritance +// to assess for overriden members (already does this). +class AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass extends Base { + override getMeaningOfLife(): number { return 12; } +} + +// Override cannot be used with optional property. +class RejectWhenOverrideOptionalProperty extends Base { + public override wasDisposed?: boolean; +} + +// If one accessor is marked override, they both should be. +class RejectWhenAccessorNotBothOverride extends Base { + override get name() { return ''; } + /* */ set name(n: string) {} +} + +// Compiler should detect when override member is not inherited or augmented +class RejectWhenOverrideMarkedOnNonInheritedMember extends Base { + public override iDontExist() { return ''; } +} + +// Compiler already detects overriden assignability mismatches, +// override keyword does not change these semantics +class RejectWhenOverrideHasMismatchedType extends Base { + override getMeaningOfLife(): string { return 'the meaning of life is a number, not a string'; } +} + +// Override is not be used on parameters +class RejectWhenOverrideIsOnAParameter { + public sayHello(override name: string) { return 'hi'; } +} + +// Override is not used on class... +override class RejectWhenOverrideIsOnClassDeclaration { public sayHello(name: string) { return ''; } } +override interface RejectWhenOverrideIsOnInterfaceDeclaration { sayHello(name: string); } + +//... or interface declarations +interface RejectWhenOverrideInAnInterface { + override sayHello(name: string); +} + +/* @mhegazy: is this an appropriate test for consecutive declarations? */ +class RejectWhenOverrideDeclarationsAreNotConsecutive extends Base { + override hasOwnProperty(prop: string): boolean { + return super.hasOwnProperty(prop); + } + + public getMeaningOfLife(): number { + return 42; + } + + override propertyIsEnumerable(prop: string): boolean { + return super.propertyIsEnumerable(prop); + } +} + + +//// [overrideKeywordEs5.js] +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var AbstractBase = (function () { + function AbstractBase() { + } + Object.defineProperty(AbstractBase.prototype, "name", { + get: function () { return this.name_; }, + set: function (name) { this.name_ = name; }, + enumerable: true, + configurable: true + }); + AbstractBase.toStringStatic = function () { return 'static'; }; + AbstractBase.prototype.toStringPublic = function () { return 'public'; }; + ; + AbstractBase.prototype.toStringProtected = function () { return 'protected'; }; + AbstractBase.prototype.toStringPrivate = function () { return 'private'; }; + AbstractBase.prototype.toStringPrivate2 = function () { return 'private2'; }; + AbstractBase.prototype.getMeaningOfLife = function () { return 42; }; + return AbstractBase; +}()); +var Base = (function (_super) { + __extends(Base, _super); + function Base() { + return _super !== null && _super.apply(this, arguments) || this; + } + Base.prototype.toStringAbstract = function () { return 'implemented'; }; + Base.prototype.toStringAbstract2 = function () { return 'implemented2'; }; + return Base; +}(AbstractBase)); +// The expected order of modifiers: +// +// [public | protected | private] [abstract | override] [static] [readonly | async] [get | set] identifier +// +var RejectWhenOverridePrecedesPublicModifier = (function (_super) { + __extends(RejectWhenOverridePrecedesPublicModifier, _super); + function RejectWhenOverridePrecedesPublicModifier() { + return _super !== null && _super.apply(this, arguments) || this; + } + RejectWhenOverridePrecedesPublicModifier.prototype.toStringPublic = function () { return ''; }; + ; + return RejectWhenOverridePrecedesPublicModifier; +}(Base)); +var RejectWhenOverridePrecedesProtectedModifier = (function (_super) { + __extends(RejectWhenOverridePrecedesProtectedModifier, _super); + function RejectWhenOverridePrecedesProtectedModifier() { + return _super !== null && _super.apply(this, arguments) || this; + } + RejectWhenOverridePrecedesProtectedModifier.prototype.toStringProtected = function () { return ''; }; + ; + return RejectWhenOverridePrecedesProtectedModifier; +}(Base)); +var RejectWhenStaticPrecedesOverrideModifier = (function (_super) { + __extends(RejectWhenStaticPrecedesOverrideModifier, _super); + function RejectWhenStaticPrecedesOverrideModifier() { + return _super !== null && _super.apply(this, arguments) || this; + } + RejectWhenStaticPrecedesOverrideModifier.toStringStatic = function () { return ''; }; + ; + return RejectWhenStaticPrecedesOverrideModifier; +}(Base)); +var AcceptWhenOverrideFollowsAccessModifier = (function (_super) { + __extends(AcceptWhenOverrideFollowsAccessModifier, _super); + function AcceptWhenOverrideFollowsAccessModifier() { + return _super !== null && _super.apply(this, arguments) || this; + } + AcceptWhenOverrideFollowsAccessModifier.prototype.toStringPublic = function () { return ''; }; + return AcceptWhenOverrideFollowsAccessModifier; +}(Base)); +var RejectWhenReadonlyPrecedesOverrideModifier = (function (_super) { + __extends(RejectWhenReadonlyPrecedesOverrideModifier, _super); + function RejectWhenReadonlyPrecedesOverrideModifier() { + return _super !== null && _super.apply(this, arguments) || this; + } + return RejectWhenReadonlyPrecedesOverrideModifier; +}(Base)); +// Modifiers should never be repeated +var RejectWhenOverrideIsRepeated = (function (_super) { + __extends(RejectWhenOverrideIsRepeated, _super); + function RejectWhenOverrideIsRepeated() { + return _super !== null && _super.apply(this, arguments) || this; + } + RejectWhenOverrideIsRepeated.prototype.toStringPublic = function () { return ''; }; + return RejectWhenOverrideIsRepeated; +}(Base)); +// You cannot override a private method +var RejectWhenOverridePrivateMethod = (function (_super) { + __extends(RejectWhenOverridePrivateMethod, _super); + function RejectWhenOverridePrivateMethod() { + return _super !== null && _super.apply(this, arguments) || this; + } + RejectWhenOverridePrivateMethod.prototype.toStringPrivate = function () { return ''; }; + RejectWhenOverridePrivateMethod.prototype.toStringPrivate2 = function () { return ''; }; + return RejectWhenOverridePrivateMethod; +}(Base)); +// Override and abstract on methods are orthogonal, should never be used together +var RejectWhenOverrideAbstractMethod = (function (_super) { + __extends(RejectWhenOverrideAbstractMethod, _super); + function RejectWhenOverrideAbstractMethod() { + return _super !== null && _super.apply(this, arguments) || this; + } + return RejectWhenOverrideAbstractMethod; +}(AbstractBase)); +// Acceptable to provide an override implementation in an abstract class however +var AcceptWhenOverrideInAbstractClass = (function (_super) { + __extends(AcceptWhenOverrideInAbstractClass, _super); + function AcceptWhenOverrideInAbstractClass() { + return _super !== null && _super.apply(this, arguments) || this; + } + AcceptWhenOverrideInAbstractClass.prototype.toStringAbstract = function () { return 'implemented in abstract class'; }; + return AcceptWhenOverrideInAbstractClass; +}(AbstractBase)); +// Override checks are allowed on static methods +var AcceptWhenOverrideStaticMethod = (function (_super) { + __extends(AcceptWhenOverrideStaticMethod, _super); + function AcceptWhenOverrideStaticMethod() { + return _super !== null && _super.apply(this, arguments) || this; + } + AcceptWhenOverrideStaticMethod.toStringStatic = function () { return 'static'; }; + return AcceptWhenOverrideStaticMethod; +}(Base)); +// Compiler already checks for access modifier narrowing, +// override does not alter these semantics. +var RejectWhenOverrideChangesAccessModifier = (function (_super) { + __extends(RejectWhenOverrideChangesAccessModifier, _super); + function RejectWhenOverrideChangesAccessModifier() { + return _super !== null && _super.apply(this, arguments) || this; + } + RejectWhenOverrideChangesAccessModifier.toStringStatic = function () { return 'member is now protected'; }; + return RejectWhenOverrideChangesAccessModifier; +}(Base)); +// Compiler should be able to traverse multiple levels of inheritance +// to assess for overriden members (already does this). +var AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass = (function (_super) { + __extends(AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass, _super); + function AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass() { + return _super !== null && _super.apply(this, arguments) || this; + } + AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass.prototype.getMeaningOfLife = function () { return 12; }; + return AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass; +}(Base)); +// Override cannot be used with optional property. +var RejectWhenOverrideOptionalProperty = (function (_super) { + __extends(RejectWhenOverrideOptionalProperty, _super); + function RejectWhenOverrideOptionalProperty() { + return _super !== null && _super.apply(this, arguments) || this; + } + return RejectWhenOverrideOptionalProperty; +}(Base)); +// If one accessor is marked override, they both should be. +var RejectWhenAccessorNotBothOverride = (function (_super) { + __extends(RejectWhenAccessorNotBothOverride, _super); + function RejectWhenAccessorNotBothOverride() { + return _super !== null && _super.apply(this, arguments) || this; + } + Object.defineProperty(RejectWhenAccessorNotBothOverride.prototype, "name", { + get: function () { return ''; }, + /* */ set: function (n) { }, + enumerable: true, + configurable: true + }); + return RejectWhenAccessorNotBothOverride; +}(Base)); +// Compiler should detect when override member is not inherited or augmented +var RejectWhenOverrideMarkedOnNonInheritedMember = (function (_super) { + __extends(RejectWhenOverrideMarkedOnNonInheritedMember, _super); + function RejectWhenOverrideMarkedOnNonInheritedMember() { + return _super !== null && _super.apply(this, arguments) || this; + } + RejectWhenOverrideMarkedOnNonInheritedMember.prototype.iDontExist = function () { return ''; }; + return RejectWhenOverrideMarkedOnNonInheritedMember; +}(Base)); +// Compiler already detects overriden assignability mismatches, +// override keyword does not change these semantics +var RejectWhenOverrideHasMismatchedType = (function (_super) { + __extends(RejectWhenOverrideHasMismatchedType, _super); + function RejectWhenOverrideHasMismatchedType() { + return _super !== null && _super.apply(this, arguments) || this; + } + RejectWhenOverrideHasMismatchedType.prototype.getMeaningOfLife = function () { return 'the meaning of life is a number, not a string'; }; + return RejectWhenOverrideHasMismatchedType; +}(Base)); +// Override is not be used on parameters +var RejectWhenOverrideIsOnAParameter = (function () { + function RejectWhenOverrideIsOnAParameter() { + } + RejectWhenOverrideIsOnAParameter.prototype.sayHello = function (name) { return 'hi'; }; + return RejectWhenOverrideIsOnAParameter; +}()); +// Override is not used on class... +var RejectWhenOverrideIsOnClassDeclaration = (function () { + function RejectWhenOverrideIsOnClassDeclaration() { + } + RejectWhenOverrideIsOnClassDeclaration.prototype.sayHello = function (name) { return ''; }; + return RejectWhenOverrideIsOnClassDeclaration; +}()); +/* @mhegazy: is this an appropriate test for consecutive declarations? */ +var RejectWhenOverrideDeclarationsAreNotConsecutive = (function (_super) { + __extends(RejectWhenOverrideDeclarationsAreNotConsecutive, _super); + function RejectWhenOverrideDeclarationsAreNotConsecutive() { + return _super !== null && _super.apply(this, arguments) || this; + } + RejectWhenOverrideDeclarationsAreNotConsecutive.prototype.hasOwnProperty = function (prop) { + return _super.prototype.hasOwnProperty.call(this, prop); + }; + RejectWhenOverrideDeclarationsAreNotConsecutive.prototype.getMeaningOfLife = function () { + return 42; + }; + RejectWhenOverrideDeclarationsAreNotConsecutive.prototype.propertyIsEnumerable = function (prop) { + return _super.prototype.propertyIsEnumerable.call(this, prop); + }; + return RejectWhenOverrideDeclarationsAreNotConsecutive; +}(Base)); + + +//// [overrideKeywordEs5.d.ts] +declare abstract class AbstractBase { + readonly id: string; + wasDisposed?: boolean; + private name_; + name: string; + static toStringStatic(): string; + toStringPublic(): string; + protected toStringProtected(): string; + private toStringPrivate(); + private toStringPrivate2(); + abstract toStringAbstract(): string; + abstract toStringAbstract2(): string; + getMeaningOfLife(): number; +} +declare class Base extends AbstractBase { + override toStringAbstract(): string; + override toStringAbstract2(): string; +} +declare class RejectWhenOverridePrecedesPublicModifier extends Base { + override toStringPublic(): string; +} +declare class RejectWhenOverridePrecedesProtectedModifier extends Base { + protected override toStringProtected(): string; +} +declare class RejectWhenStaticPrecedesOverrideModifier extends Base { + static override toStringStatic(): string; +} +declare class AcceptWhenOverrideFollowsAccessModifier extends Base { + override toStringPublic(): string; +} +declare class RejectWhenReadonlyPrecedesOverrideModifier extends Base { + override readonly id: string; +} +declare class RejectWhenOverrideIsRepeated extends Base { + override toStringPublic(): string; +} +declare class RejectWhenOverridePrivateMethod extends Base { + private override toStringPrivate(); + private override toStringPrivate2(); +} +declare abstract class RejectWhenOverrideAbstractMethod extends AbstractBase { + override abstract toStringAbstract(): string; + override abstract toStringAbstract2(): string; +} +declare abstract class AcceptWhenOverrideInAbstractClass extends AbstractBase { + override toStringAbstract(): string; +} +declare class AcceptWhenOverrideStaticMethod extends Base { + static override toStringStatic(): string; +} +declare class RejectWhenOverrideChangesAccessModifier extends Base { + protected static override toStringStatic(): string; +} +declare class AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass extends Base { + override getMeaningOfLife(): number; +} +declare class RejectWhenOverrideOptionalProperty extends Base { + override wasDisposed?: boolean; +} +declare class RejectWhenAccessorNotBothOverride extends Base { + override name: string; +} +declare class RejectWhenOverrideMarkedOnNonInheritedMember extends Base { + override iDontExist(): string; +} +declare class RejectWhenOverrideHasMismatchedType extends Base { + override getMeaningOfLife(): string; +} +declare class RejectWhenOverrideIsOnAParameter { + sayHello(name: string): string; +} +declare class RejectWhenOverrideIsOnClassDeclaration { + sayHello(name: string): string; +} +interface RejectWhenOverrideIsOnInterfaceDeclaration { + sayHello(name: string): any; +} +interface RejectWhenOverrideInAnInterface { + sayHello(name: string): any; +} +declare class RejectWhenOverrideDeclarationsAreNotConsecutive extends Base { + override hasOwnProperty(prop: string): boolean; + getMeaningOfLife(): number; + override propertyIsEnumerable(prop: string): boolean; +} diff --git a/tests/baselines/reference/overrideKeywordEs6.errors.txt b/tests/baselines/reference/overrideKeywordEs6.errors.txt new file mode 100644 index 0000000000000..2596b39a7d978 --- /dev/null +++ b/tests/baselines/reference/overrideKeywordEs6.errors.txt @@ -0,0 +1,19 @@ +tests/cases/compiler/overrideKeywordEs6.ts(11,68): error TS1029: 'override' modifier must precede 'async' modifier. + + +==== tests/cases/compiler/overrideKeywordEs6.ts (1 errors) ==== + + class Base { + async getMeaningOfLife1(): Promise { return Promise.resolve(42); } + async getMeaningOfLife2(): Promise { return Promise.reject(42); } + } + + // The expected order of modifiers: + // + // [public | protected | private] [abstract | override] [static] [readonly | async] [get | set] identifier + // + class RejectWhenAsyncPrecedesOverrideModifier extends Base { async override getMeaningOfLife1(): Promise { return Promise.reject(42); }; } + ~~~~~~~~ +!!! error TS1029: 'override' modifier must precede 'async' modifier. + class AcceptWhenOverridePrecedesAsyncModifier extends Base { override async getMeaningOfLife2(): Promise { return Promise.resolve(42); }; } + \ No newline at end of file diff --git a/tests/baselines/reference/overrideKeywordEs6.js b/tests/baselines/reference/overrideKeywordEs6.js new file mode 100644 index 0000000000000..150728dc0c74f --- /dev/null +++ b/tests/baselines/reference/overrideKeywordEs6.js @@ -0,0 +1,61 @@ +//// [overrideKeywordEs6.ts] + +class Base { + async getMeaningOfLife1(): Promise { return Promise.resolve(42); } + async getMeaningOfLife2(): Promise { return Promise.reject(42); } +} + +// The expected order of modifiers: +// +// [public | protected | private] [abstract | override] [static] [readonly | async] [get | set] identifier +// +class RejectWhenAsyncPrecedesOverrideModifier extends Base { async override getMeaningOfLife1(): Promise { return Promise.reject(42); }; } +class AcceptWhenOverridePrecedesAsyncModifier extends Base { override async getMeaningOfLife2(): Promise { return Promise.resolve(42); }; } + + +//// [overrideKeywordEs6.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class Base { + getMeaningOfLife1() { + return __awaiter(this, void 0, void 0, function* () { return Promise.resolve(42); }); + } + getMeaningOfLife2() { + return __awaiter(this, void 0, void 0, function* () { return Promise.reject(42); }); + } +} +// The expected order of modifiers: +// +// [public | protected | private] [abstract | override] [static] [readonly | async] [get | set] identifier +// +class RejectWhenAsyncPrecedesOverrideModifier extends Base { + getMeaningOfLife1() { + return __awaiter(this, void 0, void 0, function* () { return Promise.reject(42); }); + } + ; +} +class AcceptWhenOverridePrecedesAsyncModifier extends Base { + getMeaningOfLife2() { + return __awaiter(this, void 0, void 0, function* () { return Promise.resolve(42); }); + } + ; +} + + +//// [overrideKeywordEs6.d.ts] +declare class Base { + getMeaningOfLife1(): Promise; + getMeaningOfLife2(): Promise; +} +declare class RejectWhenAsyncPrecedesOverrideModifier extends Base { + override getMeaningOfLife1(): Promise; +} +declare class AcceptWhenOverridePrecedesAsyncModifier extends Base { + override getMeaningOfLife2(): Promise; +} diff --git a/tests/cases/compiler/noImplicitOverride.ts b/tests/cases/compiler/noImplicitOverride.ts index 6036d7d8d024e..ab1aa1579b79f 100644 --- a/tests/cases/compiler/noImplicitOverride.ts +++ b/tests/cases/compiler/noImplicitOverride.ts @@ -5,6 +5,7 @@ class Base { get name(): string { return 'Base'; } + getMeaningOfLife(): number { return 42; } public userId: number = 1; } @@ -15,7 +16,7 @@ class RejectWhenOverrideMissingOnInheritedMethod extends Object { } } -class RejectWhenOverrideMissingOnMethodThatMasksObjectTypeMember { +class RejectWhenOverrideMissingOnAugmentedProperty { toString(): string { return 'foo'; }; hasOwnProperty(prop: string): boolean { return false; diff --git a/tests/cases/compiler/overrideKeyword.ts b/tests/cases/compiler/overrideKeyword.ts deleted file mode 100644 index b7b0cf43baa74..0000000000000 --- a/tests/cases/compiler/overrideKeyword.ts +++ /dev/null @@ -1,89 +0,0 @@ -// @noImplicitOverride: true -// @target: es5 - -abstract class AbstractBase { - static toStringStatic(): string { return 'static member'; } - public toString(): string { return 'instance member'; }; - abstract toStringAbstract(): string; - private toStringPrivate(): string { return 'private member'; } - getMeaningOfLife(): number { return 42; } - public wasDisposed?: boolean; -} - -class Base extends AbstractBase { - private name_: string; - - toStringAbstract(): string { return 'implementation of abstract member'; }; - - get name() { - return this.name_; - } - - set name(name: string) { - this.name_ = name; - } - - // override cannot be used with optional property. - public override wasDisposed?: boolean; -} - -abstract class RejectWhenAttemptToOverrideAbstractMethod extends AbstractBase { - abstract override toStringAbstract(): string; -} - -class RejectWhenAttemptToOverrideStaticMethod extends Base { - override static toStringStatic() { return ''; }; -} - -class RejectWhenAttemptToOverridePrivateMethod extends Base { - private override toStringPrivate() { return ''; }; -} - -class RejectWhenOverrideIsRepeated extends Base { - public override override toString() { return ''; }; -} - -class RejectWhenOverridePrecedesAccessModifier extends Base { - override public toString() { return ''; }; -} - -class RejectWhenOverrideMarkedOnNonInheritedMember extends Base { - public override iDontExist() { return ''; }; -} - -class RejectWhenOverrideHasMismatchedType extends Base { - override getMeaningOfLife(): string { return 'forty-two'; }; -} - -class RejectWhenAccessorNotBothOverride extends Base { - override get name() { - return 'hardcoded value'; - } - set name(n: string) { - } -} - -/* @mhegazy: is this an appropriate test for consecutive declarations? */ -class RejectWhenOverrideDeclarationsAreNotConsecutive extends Base { - - override hasOwnProperty(prop: string): boolean { - return super.hasOwnProperty(prop); - } - - public getMeaningOfLife(): number { - return 42; - } - - override propertyIsEnumerable(prop: string): boolean { - return super.propertyIsEnumerable(prop); - } - -} - -class AcceptWhenOverrideFollowsAccessModifier extends Base { - public override toString() { return ''; }; -} - -class AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass extends Base { - public override getMeaningOfLife(): number { return 12; }; -} diff --git a/tests/cases/compiler/overrideKeywordEs5.ts b/tests/cases/compiler/overrideKeywordEs5.ts new file mode 100644 index 0000000000000..c72dc83c55970 --- /dev/null +++ b/tests/cases/compiler/overrideKeywordEs5.ts @@ -0,0 +1,126 @@ +// @declaration: true +// @noImplicitOverride: false +// @target: es5 + +abstract class AbstractBase { + readonly id: string; + public wasDisposed?: boolean; + private name_: string; + get name() { return this.name_; } + set name(name: string) { this.name_ = name; } + + static toStringStatic(): string { return 'static'; } + public toStringPublic(): string { return 'public'; }; + protected toStringProtected(): string { return 'protected'; } + private toStringPrivate(): string { return 'private'; } + private toStringPrivate2(): string { return 'private2'; } + abstract toStringAbstract(): string; + abstract toStringAbstract2(): string; + + getMeaningOfLife(): number { return 42; } +} + +class Base extends AbstractBase { + override toStringAbstract(): string { return 'implemented'; } + override toStringAbstract2(): string { return 'implemented2'; } +} + +// The expected order of modifiers: +// +// [public | protected | private] [abstract | override] [static] [readonly | async] [get | set] identifier +// +class RejectWhenOverridePrecedesPublicModifier extends Base { override public toStringPublic() { return ''; }; } +class RejectWhenOverridePrecedesProtectedModifier extends Base { override protected toStringProtected() { return ''; }; } +class RejectWhenStaticPrecedesOverrideModifier extends Base { static override toStringStatic() { return ''; }; } +class AcceptWhenOverrideFollowsAccessModifier extends Base { public override toStringPublic() { return ''; } } +class RejectWhenReadonlyPrecedesOverrideModifier extends Base { readonly override id: string; } + +// Modifiers should never be repeated +class RejectWhenOverrideIsRepeated extends Base { + public override override toStringPublic() { return ''; } +} + +// You cannot override a private method +class RejectWhenOverridePrivateMethod extends Base { + private override toStringPrivate() { return ''; } + override private toStringPrivate2() { return ''; } +} + +// Override and abstract on methods are orthogonal, should never be used together +abstract class RejectWhenOverrideAbstractMethod extends AbstractBase { + abstract override toStringAbstract(): string; + override abstract toStringAbstract2(): string; +} + +// Acceptable to provide an override implementation in an abstract class however +abstract class AcceptWhenOverrideInAbstractClass extends AbstractBase { + override toStringAbstract(): string { return 'implemented in abstract class'; } +} + +// Override checks are allowed on static methods +class AcceptWhenOverrideStaticMethod extends Base { + override static toStringStatic() { return 'static'; } +} + +// Compiler already checks for access modifier narrowing, +// override does not alter these semantics. +class RejectWhenOverrideChangesAccessModifier extends Base { + protected override static toStringStatic() { return 'member is now protected'; } +} + +// Compiler should be able to traverse multiple levels of inheritance +// to assess for overriden members (already does this). +class AcceptWhenOverrideMemberExistsOnNonImmediateSuperclass extends Base { + override getMeaningOfLife(): number { return 12; } +} + +// Override cannot be used with optional property. +class RejectWhenOverrideOptionalProperty extends Base { + public override wasDisposed?: boolean; +} + +// If one accessor is marked override, they both should be. +class RejectWhenAccessorNotBothOverride extends Base { + override get name() { return ''; } + /* */ set name(n: string) {} +} + +// Compiler should detect when override member is not inherited or augmented +class RejectWhenOverrideMarkedOnNonInheritedMember extends Base { + public override iDontExist() { return ''; } +} + +// Compiler already detects overriden assignability mismatches, +// override keyword does not change these semantics +class RejectWhenOverrideHasMismatchedType extends Base { + override getMeaningOfLife(): string { return 'the meaning of life is a number, not a string'; } +} + +// Override is not be used on parameters +class RejectWhenOverrideIsOnAParameter { + public sayHello(override name: string) { return 'hi'; } +} + +// Override is not used on class... +override class RejectWhenOverrideIsOnClassDeclaration { public sayHello(name: string) { return ''; } } +override interface RejectWhenOverrideIsOnInterfaceDeclaration { sayHello(name: string); } + +//... or interface declarations +interface RejectWhenOverrideInAnInterface { + override sayHello(name: string); +} + +/* @mhegazy: is this an appropriate test for consecutive declarations? */ +class RejectWhenOverrideDeclarationsAreNotConsecutive extends Base { + override hasOwnProperty(prop: string): boolean { + return super.hasOwnProperty(prop); + } + + public getMeaningOfLife(): number { + return 42; + } + + override propertyIsEnumerable(prop: string): boolean { + return super.propertyIsEnumerable(prop); + } +} diff --git a/tests/cases/compiler/overrideKeywordEs6.ts b/tests/cases/compiler/overrideKeywordEs6.ts new file mode 100644 index 0000000000000..a6f3d6a530034 --- /dev/null +++ b/tests/cases/compiler/overrideKeywordEs6.ts @@ -0,0 +1,15 @@ +// @declaration: true +// @noImplicitOverride: false +// @target: es6 + +class Base { + async getMeaningOfLife1(): Promise { return Promise.resolve(42); } + async getMeaningOfLife2(): Promise { return Promise.reject(42); } +} + +// The expected order of modifiers: +// +// [public | protected | private] [abstract | override] [static] [readonly | async] [get | set] identifier +// +class RejectWhenAsyncPrecedesOverrideModifier extends Base { async override getMeaningOfLife1(): Promise { return Promise.reject(42); }; } +class AcceptWhenOverridePrecedesAsyncModifier extends Base { override async getMeaningOfLife2(): Promise { return Promise.resolve(42); }; }