TypeScript is a superset of JavaScript. That means that the TypeScript language includes the entire JavaScript language plus a collection of useful additional features. This contrasts with the various subsets of JavaScript and the various linting tools that seek to reduce the available features to create a smaller language with fewer surprises. This chapter will introduce you to the extra language features, starting with simple type annotations and progressing to more advanced features and structural elements of TypeScript. This chapter doesnt cover every feature included in the ECMAScript language specification, so if you need a refresher on JavaScript, take a look at Appendix 1.
The basic building blocks of your program will come from JavaScript, including if statements, switch statements, loops, arithmetic, logical tests, and functions. This is one of the key strengths of TypeScript it is based on a language (and a family of languages) that is already familiar to a vast and varied collection of programmers. JavaScript is thoroughly documented not only in the ECMA-262 specification, but also in books, on developer network portals, forums, and question-and-answer websites. When features are added to JavaScript, they will also appear in TypeScript.
The TypeScript compiler is typically updated with new JavaScript features early in their specification. Most of the features are available before browsers support them. In many cases, you can use the features in your TypeScript program as the compiler will convert them into code that targets the older versions of the ECMAScript standard.
Each of the language features discussed in this chapter has short, self-contained code examples that put the feature in context. For the purposes of introducing and explaining features, the examples are short and to the point; this allows the chapter to be read end to end. However, this also means you can refer back to the chapter as a reference later on. Once you have read this chapter, you should know everything you will need to understand the more complex examples described throughout the rest of the book.
JavaScript Is Valid TypeScript
Before we find out more about the TypeScript syntax, it is worth stressing one important fact: All JavaScript is valid TypeScript. You dont need to discard any of your JavaScript know-how as it can all be transferred directly to your TypeScript code. You can take existing JavaScript code, add it to a TypeScript file, and all the statements will be valid. There is a subtle difference between valid code and error-free code in TypeScript; because, although your code may work, the TypeScript compiler will warn you about any potential problems it has detected. Finding subtle and previously undetected bugs is a common story shared by programmers making the transition to TypeScript.
If you transfer a JavaScript listing into a TypeScript file, you may receive errors or warnings even though the code is considered valid. A common example comes from the dynamic type system in JavaScript wherein it is perfectly acceptable to assign values of different types to the same variable during its lifetime. TypeScript detects these assignments and generates errors to warn you that the type of the variable has been changed by the assignment. Because this is a common cause of errors in a program, you can correct the error by creating separate variables, by performing a type assertion, or by making the variable dynamic. There is further information on type annotations later in this chapter, and the type system is discussed in detail in Chapter .
Unlike some compilers that will only create output where no compilation errors are detected, the TypeScript compiler will still attempt to generate sensible JavaScript code. The TypeScript code shown in Listing generates an error, but the JavaScript output is still produced. This is an admirable feature, but as always with compiler warnings and errors, you should correct the problem in your source code and get a clean compilation. If you routinely ignore these messages, your program will eventually exhibit unexpected behavior. In some cases, your listing may contain errors that are so severe that the TypeScript compiler wont be able to generate the JavaScript output.
Caution
The only exceptions to the all JavaScript is valid TypeScript rule are the with statement and vendor-specific extensions, until they are formally added to the ECMAScript specification. You could technically still use the with statement, but all statements within the block would be unchecked.
The JavaScript with statement in Listing shows two examples of the same routine. Although the first calls Math.PI explicitly, the second uses a with statement, which adds the properties and functions of Math to the current scope. Statements nested inside the with statement can omit the Math prefix and call properties and functions directly, for example, the PI property or the floor function.
At the end of the with statement, the original lexical scope is restored, so subsequent calls outside of the with block must use the Math prefix.
// Not using with
const radius1 = 4;
const area1 = Math.PI * radius1 * radius1;
// Using with
const radius2 = 4;
with (Math) {
const area2 = PI * radius2 * radius2;
}
Listing 1-1.
Using JavaScripts with statement
The with statement was not allowed in strict mode in ECMAScript 5 and later versions of ECMAScript use strict mode by default for classes and modules. TypeScript treats with statements as an error and will treat all types within the with statement as dynamic types. This is due to the following:
The fact it is disallowed in strict mode.
The general opinion that the with statement is dangerous.
The practical issues of determining the identifiers that are in scope at compile time.
So, with these minor exceptions to the rule in mind, you can place any valid JavaScript into a TypeScript file and it will be valid TypeScript. As an example, here is the area calculation script transferred to a TypeScript file.
Note
The ECMAScript 6 specification, also known as ES6 Harmony, represented a substantial change to the JavaScript language. The specification has been divided into annual chunks, released as ECMAScript 2015, ECMAScript 2016, and so on.
const radius = 4;
const area = Math.PI * radius * radius;
Listing 1-2.
Transferring JavaScript in to a TypeScript file
In Listing , the statements are just plain JavaScript, but in TypeScript the variables radius and area will both benefit from type inference. Because radius is initialized with the value , it can be inferred that the type of radius is number . With just a slight increase in effort, the result of multiplying Math.PI , which is known to be a number , with the radius variable that has been inferred to be a number , it is possible to infer the type of area is also a number .