Advanced Combinations

Advanced Combinations Some kinds of declarations can be combined across multiple declarations. For example, class C { } and interface C { } can co-exist and both contribute properties to the C types. This is legal as long as it does not create a conflict. A general rule of thumb is that values always conflict with other values of the same name unless they are declared as namespaces, types will conflict if they are declared with a type alias declaration (type s = string), and namespaces never co

Multi-file namespaces

Multi-file namespaces Here, we’ll split our Validation namespace across many files. Even though the files are separate, they can each contribute to the same namespace and can be consumed as if they were all defined in one place. Because there are dependencies between files, we’ll add reference tags to tell the compiler about the relationships between the files. Our test code is otherwise unchanged. Validation.ts namespace Validation { export interface StringValidator { isAcceptable(s: str

Parameter properties

Parameter properties In our last example, we had to declare a readonly member name and a constructor parameter theName in the Octopus class, and we then immediately set name to theName. This turns out to be a very common practice. Parameter properties let you create and initialize a member in one place. Here’s a further revision of the previous Octopus class using a parameter property: class Octopus { readonly numberOfLegs: number = 8; constructor(readonly name: string) { } } Notice how

The Impact of ES6 on Module Plugins

The Impact of ES6 on Module Plugins Some plugins add or modify top-level exports on existing modules. While this is legal in CommonJS and other loaders, ES6 modules are considered immutable and this pattern will not be possible. Because TypeScript is loader-agnostic, there is no compile-time enforcement of this policy, but developers intending to transition to an ES6 module loader should be aware of this.

<reference>-ing a module

/// <reference>-ing a module A common mistake is to try to use the /// <reference ... /> syntax to refer to a module file, rather than using an import statement. To understand the distinction, we first need to understand how compiler can locate the type information for a module based on the path of an import (e.g. the ... in import x from "...";, import x = require("...");, etc.) path. The compiler will try to find a .ts, .tsx, and then a .d.ts with the appropriate path. If a speci

Writing a Configuration File

Writing a Configuration File TypeScript uses a file called tsconfig.json for managing your project’s options, such as which files you want to include, and what sorts of checking you want to perform. Let’s create a bare-bones one for our project: { "compilerOptions": { "outDir": "./built", "allowJs": true, "target": "es5" }, "include": [ "./src" ] } Here we’re specifying a few things to TypeScript: Read in any files it understands in the src directory (with include). Acc

global.d.ts

// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] // Project: [~THE PROJECT NAME~] // Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]> /*~ If this library is callable (e.g. can be invoked as myLib(3)), *~ include those call signatures here. *~ Otherwise, delete this section. */ declare function myLib(a: string): string; declare function myLib(a: number): number; /*~ If you want the name of this library to be a valid type name, *~ you can do so here. *~ *~ F

global-plugin.d.ts

// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] // Project: [~THE PROJECT NAME~] // Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]> /*~ This template shows how to write a global plugin. */ /*~ Write a declaration for the original type and add new members. *~ For example, this adds a 'toBinaryString' method with to overloads to *~ the built-in number type. */ interface Number { toBinaryString(opts?: MyLibrary.BinaryFormatOptions): string; toBinaryString(

Intrinsic elements

Intrinsic elements Intrinsic elements are looked up on the special interface JSX.IntrinsicElements. By default, if this interface is not specified, then anything goes and intrinsic elements will not be type checked. However, if interface is present, then the name of the intrinsic element is looked up as a property on the JSX.IntrinsicElements interface. For example: declare namespace JSX { interface IntrinsicElements { foo: any } } <foo />; // ok <bar />; // error In the a

Add example code

Add example code Type the following code into app.ts. function sayHello() { const compiler = (document.getElementById("compiler") as HTMLInputElement).value; const framework = (document.getElementById("framework") as HTMLInputElement).value; return `Hello from ${compiler} and ${framework}!`; }