typeof type guards

typeof type guards Let’s go back and write the code for the version of padLeft that uses union types. We could write it with type predicates as follows: function isNumber(x: any): x is number { return typeof x === "number"; } function isString(x: any): x is string { return typeof x === "string"; } function padLeft(value: string, padding: string | number) { if (isNumber(padding)) { return Array(padding + 1).join(" ") + value; } if (isString(padding)) { return padding + value

Tuple

Tuple Tuple types allow you to express an array where the type of a fixed number of elements is known, but need not be the same. For example, you may want to represent a value as a pair of a string and a number: // Declare a tuple type let x: [string, number]; // Initialize it x = ["hello", 10]; // OK // Initialize it incorrectly x = [10, "hello"]; // Error When accessing an element with a known index, the correct type is retrieved: console.log(x[0].substr(1)); // OK console.log(x[1].substr(1)

Type assertions

Type assertions Sometimes you’ll end up in a situation where you’ll know more about a value than TypeScript does. Usually this will happen when you know the type of some entity could be more specific than its current type. Type assertions are a way to tell the compiler “trust me, I know what I’m doing.” A type assertion is like a type cast in other languages, but performs no special checking or restructuring of data. It has no runtime impact, and is used purely by the compiler. TypeScript assum

Type Aliases

Type Aliases Type aliases create a new name for a type. Type aliases are sometimes similar to interfaces, but can name primitives, unions, tuples, and any other types that you’d otherwise have to write by hand. type Name = string; type NameResolver = () => string; type NameOrResolver = Name | NameResolver; function getName(n: NameOrResolver): Name { if (typeof n === "string") { return n; } else { return n(); } } Aliasing doesn’t actually create a new type - it creates a new

Type Checking

Type Checking In order to understand type checking with JSX, you must first understand the difference between intrinsic elements and value-based elements. Given a JSX expression <expr />, expr may either refer to something intrinsic to the environment (e.g. a div or span in a DOM environment) or to a custom component that you’ve created. This is important for two reasons: For React, intrinsic elements are emitted as strings (React.createElement("div")), whereas a component you’ve created

this and arrow functions

this and arrow functions In JavaScript, this is a variable that’s set when a function is called. This makes it a very powerful and flexible feature, but it comes at the cost of always having to know about the context that a function is executing in. This is notoriously confusing, especially when returning a function or passing a function as an argument. Let’s look at an example: let deck = { suits: ["hearts", "spades", "clubs", "diamonds"], cards: Array(52), createCardPicker: function()

this parameters

this parameters Unfortunately, the type of this.suits[pickedSuit] is still any. That’s because this comes from the function expression inside the object literal. To fix this, you can provide an explicit this parameter. this parameters are fake parameters that come first in the parameter list of a function: function f(this: void) { // make sure `this` is unusable in this standalone function } Let’s add a couple of interfaces to our example above, Card and Deck, to make the types clearer and

toStringTag

Symbol.toStringTag A String value that is used in the creation of the default string description of an object. Called by the built-in method Object.prototype.toString.

toPrimitive

Symbol.toPrimitive A method that converts an object to a corresponding primitive value. Called by the ToPrimitive abstract operation.

Tracing module resolution

Tracing module resolution As discussed earlier, the compiler can visit files outside the current folder when resolving a module. This can be hard when diagnosing why a module is not resolved, or is resolved to an incorrect definition. Enabling the compiler module resolution tracing using --traceResolution provides insight in what happened during the module resolution process. Let’s say we have a sample application that uses the typescript module. app.ts has an import like import * as ts from "t