Type Script Notes For Professionals
Type Script Notes For Professionals
TypeScript
Notes for Professionals
80+ pages
of professional hints and tricks
Disclaimer
GoalKicker.com This is an unocial free book created for educational purposes and is
not aliated with ocial TypeScript group(s) or company(s).
Free Programming Books All trademarks and registered trademarks are
the property of their respective owners
Contents
About ................................................................................................................................................................................... 1
Chapter 1: Getting started with TypeScript .................................................................................................... 2
Section 1.1: Installation and setup ................................................................................................................................. 2
Section 1.2: Basic syntax ............................................................................................................................................... 4
Section 1.3: Hello World ................................................................................................................................................. 5
Section 1.4: Running TypeScript using ts-node .......................................................................................................... 6
Section 1.5: TypeScript REPL in Node.js ....................................................................................................................... 6
Chapter 2: Why and when to use TypeScript ................................................................................................. 8
Section 2.1: Safety .......................................................................................................................................................... 8
Section 2.2: Readability ................................................................................................................................................ 8
Section 2.3: Tooling ....................................................................................................................................................... 8
Chapter 3: TypeScript Core Types ....................................................................................................................... 9
Section 3.1: String Literal Types .................................................................................................................................... 9
Section 3.2: Tuple ........................................................................................................................................................ 12
Section 3.3: Boolean .................................................................................................................................................... 12
Section 3.4: Intersection Types .................................................................................................................................. 13
Section 3.5: Types in function arguments and return value. Number ................................................................... 13
Section 3.6: Types in function arguments and return value. String ....................................................................... 14
Section 3.7: const Enum .............................................................................................................................................. 14
Section 3.8: Number .................................................................................................................................................... 15
Section 3.9: String ........................................................................................................................................................ 15
Section 3.10: Array ....................................................................................................................................................... 16
Section 3.11: Enum ........................................................................................................................................................ 16
Section 3.12: Any .......................................................................................................................................................... 16
Section 3.13: Void ......................................................................................................................................................... 16
Chapter 4: Arrays ....................................................................................................................................................... 17
Section 4.1: Finding Object in Array ........................................................................................................................... 17
Chapter 5: Enums ........................................................................................................................................................ 18
Section 5.1: Enums with explicit values ...................................................................................................................... 18
Section 5.2: How to get all enum values ................................................................................................................... 19
Section 5.3: Extending enums without custom enum implementation .................................................................. 19
Section 5.4: Custom enum implementation: extends for enums ............................................................................ 19
Chapter 6: Functions ................................................................................................................................................. 21
Section 6.1: Optional and Default Parameters ......................................................................................................... 21
Section 6.2: Function as a parameter ....................................................................................................................... 21
Section 6.3: Functions with Union Types ................................................................................................................... 23
Section 6.4: Types of Functions ................................................................................................................................. 23
Chapter 7: Classes ...................................................................................................................................................... 24
Section 7.1: Abstract Classes ...................................................................................................................................... 24
Section 7.2: Simple class ............................................................................................................................................. 24
Section 7.3: Basic Inheritance ..................................................................................................................................... 25
Section 7.4: Constructors ............................................................................................................................................ 25
Section 7.5: Accessors ................................................................................................................................................. 26
Section 7.6: Transpilation ........................................................................................................................................... 27
Section 7.7: Monkey patch a function into an existing class .................................................................................. 28
Chapter 8: Class Decorator ................................................................................................................................... 29
Section 8.1: Generating metadata using a class decorator .................................................................................... 29
Section 8.2: Passing arguments to a class decorator ............................................................................................. 29
Section 8.3: Basic class decorator ............................................................................................................................. 30
Chapter 9: Interfaces ................................................................................................................................................ 32
Section 9.1: Extending Interface ................................................................................................................................. 32
Section 9.2: Class Interface ........................................................................................................................................ 32
Section 9.3: Using Interfaces for Polymorphism ...................................................................................................... 33
Section 9.4: Generic Interfaces .................................................................................................................................. 34
Section 9.5: Add functions or properties to an existing interface .......................................................................... 35
Section 9.6: Implicit Implementation And Object Shape ......................................................................................... 35
Section 9.7: Using Interfaces to Enforce Types ....................................................................................................... 36
Chapter 10: Generics ................................................................................................................................................. 37
Section 10.1: Generic Interfaces .................................................................................................................................. 37
Section 10.2: Generic Class ......................................................................................................................................... 37
Section 10.3: Type parameters as constraints ......................................................................................................... 38
Section 10.4: Generics Constraints ............................................................................................................................. 38
Section 10.5: Generic Functions .................................................................................................................................. 39
Section 10.6: Using generic Classes and Functions: ................................................................................................. 39
Chapter 11: Strict null checks ................................................................................................................................ 40
Section 11.1: Strict null checks in action ...................................................................................................................... 40
Section 11.2: Non-null assertions ................................................................................................................................ 40
Chapter 12: User-defined Type Guards ........................................................................................................... 42
Section 12.1: Type guarding functions ....................................................................................................................... 42
Section 12.2: Using instanceof .................................................................................................................................... 43
Section 12.3: Using typeof ........................................................................................................................................... 43
Chapter 13: TypeScript basic examples .......................................................................................................... 45
Section 13.1: 1 basic class inheritance example using extends and super keyword ............................................. 45
Section 13.2: 2 static class variable example - count how many time method is being invoked ....................... 45
Chapter 14: Importing external libraries ........................................................................................................ 46
Section 14.1: Finding definition files ............................................................................................................................ 46
Section 14.2: Importing a module from npm ............................................................................................................ 47
Section 14.3: Using global external libraries without typings .................................................................................. 47
Section 14.4: Finding definition files with TypeScript 2.x .......................................................................................... 47
Chapter 15: Modules - exporting and importing ......................................................................................... 49
Section 15.1: Hello world module ................................................................................................................................ 49
Section 15.2: Re-export ............................................................................................................................................... 49
Section 15.3: Exporting/Importing declarations ....................................................................................................... 51
Chapter 16: Publish TypeScript definition files ............................................................................................ 52
Section 16.1: Include definition file with library on npm ........................................................................................... 52
Chapter 17: Using TypeScript with webpack ................................................................................................ 53
Section 17.1: webpack.config.js ................................................................................................................................... 53
Chapter 18: Mixins ....................................................................................................................................................... 54
Section 18.1: Example of Mixins .................................................................................................................................. 54
Chapter 19: How to use a JavaScript library without a type definition file ................................. 55
Section 19.1: Make a module that exports a default any ......................................................................................... 55
Section 19.2: Declare an any global .......................................................................................................................... 55
Section 19.3: Use an ambient module ....................................................................................................................... 56
Chapter 20: TypeScript installing typescript and running the typescript compiler tsc ........ 57
Section 20.1: Steps ....................................................................................................................................................... 57
Chapter 21: Configure typescript project to compile all files in typescript. ................................ 59
Section 21.1: TypeScript Configuration file setup ..................................................................................................... 59
Chapter 22: Integrating with Build Tools ........................................................................................................ 61
Section 22.1: Browserify .............................................................................................................................................. 61
Section 22.2: Webpack ............................................................................................................................................... 61
Section 22.3: Grunt ...................................................................................................................................................... 62
Section 22.4: Gulp ........................................................................................................................................................ 62
Section 22.5: MSBuild .................................................................................................................................................. 63
Section 22.6: NuGet ..................................................................................................................................................... 63
Section 22.7: Install and configure webpack + loaders ........................................................................................... 64
Chapter 23: Using TypeScript with RequireJS ............................................................................................. 65
Section 23.1: HTML example using RequireJS CDN to include an already compiled TypeScript file ................. 65
Section 23.2: tsconfig.json example to compile to view folder using RequireJS import style ............................ 65
Chapter 24: TypeScript with AngularJS ......................................................................................................... 66
Section 24.1: Directive ................................................................................................................................................. 66
Section 24.2: Simple example .................................................................................................................................... 67
Section 24.3: Component ............................................................................................................................................ 67
Chapter 25: TypeScript with SystemJS ........................................................................................................... 69
Section 25.1: Hello World in the browser with SystemJS ......................................................................................... 69
Chapter 26: Using TypeScript with React (JS & native) ......................................................................... 72
Section 26.1: ReactJS component written in TypeScript ......................................................................................... 72
Section 26.2: TypeScript & react & webpack ........................................................................................................... 73
Chapter 27: TSLint - assuring code quality and consistency ............................................................... 75
Section 27.1: Configuration for fewer programming errors .................................................................................... 75
Section 27.2: Installation and setup ........................................................................................................................... 75
Section 27.3: Sets of TSLint Rules .............................................................................................................................. 76
Section 27.4: Basic tslint.json setup ........................................................................................................................... 76
Section 27.5: Using a predefined ruleset as default ................................................................................................ 76
Chapter 28: tsconfig.json ........................................................................................................................................ 78
Section 28.1: Create TypeScript project with tsconfig.json ..................................................................................... 78
Section 28.2: Configuration for fewer programming errors ................................................................................... 79
Section 28.3: compileOnSave ..................................................................................................................................... 80
Section 28.4: Comments ............................................................................................................................................. 80
Section 28.5: preserveConstEnums ........................................................................................................................... 81
Chapter 29: Debugging ............................................................................................................................................ 82
Section 29.1: TypeScript with ts-node in WebStorm ................................................................................................ 82
Section 29.2: TypeScript with ts-node in Visual Studio Code ................................................................................. 83
Section 29.3: JavaScript with SourceMaps in Visual Studio Code .......................................................................... 84
Section 29.4: JavaScript with SourceMaps in WebStorm ....................................................................................... 84
Chapter 30: Unit Testing ......................................................................................................................................... 86
Section 30.1: tape ......................................................................................................................................................... 86
Section 30.2: jest (ts-jest) ........................................................................................................................................... 87
Section 30.3: Alsatian .................................................................................................................................................. 89
Section 30.4: chai-immutable plugin ......................................................................................................................... 89
Credits .............................................................................................................................................................................. 91
You may also like ........................................................................................................................................................ 93
About
Please feel free to share this PDF with anyone for free,
latest version of this book can be downloaded from:
https://goalkicker.com/TypeScriptBook
This TypeScript Notes for Professionals book is compiled from Stack Overflow
Documentation, the content is written by the beautiful people at Stack Overflow.
Text content is released under Creative Commons BY-SA, see credits at the end
of this book whom contributed to the various chapters. Images may be copyright
of their respective owners unless otherwise specified
This is an unofficial free book created for educational purposes and is not
affiliated with official TypeScript group(s) or company(s) nor Stack Overflow. All
trademarks and registered trademarks are the property of their respective
company owners
TypeScript is a typed superset of JavaScript that compiles directly to JavaScript code. TypeScript files commonly use
the .ts extension. Many IDEs support TypeScript without any other setup required, but TypeScript can also be
compiled with the TypeScript Node.JS package from the command line.
Visual Studio Code (vscode) provides contextual autocomplete as well as refactoring and debugging tools for
TypeScript. vscode is itself implemented in TypeScript. Available for Mac OS X, Windows and Linux.
WebStorm
WebStorm 2016.2 comes with TypeScript and a built-in compiler. [WebStorm is not free]
IntelliJ IDEA
IntelliJ IDEA 2016.2 has support for TypeScript and a compiler via a plugin maintained by the JetBrains
team. [IntelliJ is not free]
Sublime Text
You can install TypeScript globally to have access to it from any directory.
or
You can install TypeScript locally and save to package.json to restrict to a directory.
The tsc compilation command comes with typescript, which can be used to compile code.
tsc my-code.ts
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false,
"pretty": true
},
"exclude": [
"node_modules"
]
}
With a tsconfig.json file placed at the root of your TypeScript project, you can use the tsc command to run the
compilation.
TypeScript makes JavaScript more like a strongly-typed, object-oriented language akin to C# and Java. This means
that TypeScript code tends to be easier to use for large projects and that code tends to be easier to understand and
maintain. The strong typing also means that the language can (and is) precompiled and that variables cannot be
assigned values that are out of their declared range. For instance, when a TypeScript variable is declared as a
number, you cannot assign a text value to it.
This strong typing and object orientation makes TypeScript easier to debug and maintain, and those were two of
the weakest points of standard JavaScript.
Type declarations
You can add type declarations to variables, function parameters and function return types. The type is written after
a colon following the variable name, like this: var num: number = 5; The compiler will then check the types (where
possible) during compilation and report type errors.
null - type for the value null. null is implicitly part of every type, unless strict null checks are enabled.
Casting
You can perform explicit casting through angle brackets, for instance:
This example shows a derived class which is treated by the compiler as a MyInterface. Without the casting on the
second line the compiler would throw an exception as it does not understand someSpecificMethod(), but casting
through <ImplementingClass>derived suggests the compiler what to do.
Since TypeScript 1.6, the default is using the as keyword, because using <> is ambiguous in .jsx files. This is
mentioned in TypeScript official documentation.
Classes
Classes can be defined and used in TypeScript code. To learn more about classes, see the Classes documentation
page.
constructor(message: string) {
this.greeting = message;
}
greet(): string {
return this.greeting;
}
};
Here we have a class, Greeter, that has a constructor and a greet method. We can construct an instance of the
class using the new keyword and pass in a string we want the greet method to output to the console. The instance
of our Greeter class is stored in the greeter variable which we then us to call the greet method.
ts-node does not bundle typescript compiler, so you might need to install it.
Executing script
ts-node main.ts
// main.ts
console.log("Hello world");
Example usage
$ ts-node main.ts
Hello world
Running REPL
Example usage
$ ts-node
> const sum = (a, b): number => a + b;
undefined
> sum(2, 2)
4
> .exit
Usage example:
$ tsun
TSUN : TypeScript Upgraded Node
type in TypeScript expression to evaluate
type :help for commands in repl
$ function multiply(x, y) {
..return x * y;
..}
undefined
$ multiply(3, 4)
12
It brings many of the advantages of type system (safety, readability, improved tooling) to the JavaScript ecosystem.
It also suffers from some of the drawbacks of type systems (added complexity and incompleteness).
You'll never forget whether String.prototype.slice takes (start, stop) or (start, length) again!
Here, for instance, Visual Studio Code is able to rename references to the inner foo without altering the outer foo.
This would be difficult to do with a simple find/replace.
Together with Type Aliases and Union Types you get a enum-like behavior.
// Error: Argument of type '"rock"' is not assignable to parameter of type "'cat' | "dog" | "bird".
Type '"rock"' is not assignable to type '"bird"'.
// buyPet("rock", "Rocky");
interface Pet {
species: Species;
eat();
sleep();
}
interface Pet {
species: Species;
name: string;
eat();
walk();
sleep();
}
// Error: Interface 'Rock' incorrectly extends interface 'Pet'. Types of property 'species' are
incompatible. Type '"rock"' is not assignable to type '"cat" | "dog" | "bird"'. Type '"rock"' is not
assignable to type '"bird"'.
// interface Rock extends Pet {
// type: "rock";
// }
if(petIsCat(pet)) {
// pet is now from type Cat (pet: Cat)
pet.eat();
pet.sleep();
} else if(petIsDog(pet)) {
// pet is now from type Dog (pet: Dog)
pet.eat();
pet.walk();
pet.sleep();
} else if(petIsBird(pet)) {
// pet is now from type Bird (pet: Bird)
pet.eat();
pet.sing();
pet.sleep();
} else {
throw "An unknown pet. Did you buy a rock?";
}
}
// Error: Argument of type '"rock"' is not assignable to parameter of type "'cat' | "dog" | "bird".
Type '"rock"' is not assignable to type '"bird"'.
// buyPet("rock", "Rocky");
playWithPet(dog);
// Output: Hey Rocky, lets play.
// Rocky eats.
// Rocky walks.
// Rocky sleeps.
interface Knife {
cut();
}
interface BottleOpener{
openBottle();
}
interface Screwdriver{
turnScrew();
}
tool.cut();
tool.openBottle();
tool.turnScrew();
}
Example:
Here the syntax x: number, y: number means that the function can accept two argumentsx and y and they can
only be numbers and (...): number { means that the return value can only be a number
Usage:
Note:
or
error TS2322: Type 'string' is not assignable to type 'number' and error TS2322: Type 'number' is
not assignable to type 'string' respectively
Here the syntax name: string means that the function can accept one name argument and this argument can only
be string and (...): string { means that the return value can only be a string
Usage:
// TypeScript: A const Enum can be defined like a normal Enum (with start value, specific values,
etc.)
const enum NinjaActivity {
Espionage,
Sabotage,
Assassination
}
// JavaScript: Then only the number of the value is compiled into the code
// var myFavoriteNinjaActivity = 0 /* Espionage */;
// console.log(myFavoritePirateActivity); // 0
// JavaScript: Just the number and in a comment the name of the value
// console.log(1 /* "Sabotage" */); // 1
or assign values:
function findCherries(fruit) {
return fruit.name === 'cherries';
}
/* OR */
enum MimeType {
JPEG,
PNG,
PDF
}
But some of the time it is important to have the enum resolve to a different type. E.g. you receive the value from
backend / frontend / another system which is definitely a string. This could be a pain, but luckily there is this
method:
enum MimeType {
JPEG = <any>'image/jpeg',
PNG = <any>'image/png',
PDF = <any>'application/pdf'
}
enum MimeType {
JPEG = 'image/jpeg',
PNG = 'image/png',
PDF = 'application/pdf',
}
You can explicitly provide numeric values using the same method
enum MyType {
Value = 3,
ValueEx = 30,
ValueEx2 = 300
}
Fancier types also work, since non-const enums are real objects at runtime, for example
enum FancyType {
OneArr = <any>[1],
TwoArr = <any>[2, 2],
ThreeArr = <any>[3, 3, 3]
}
becomes
var FancyType;
(function (FancyType) {
FancyType[FancyType["OneArr"] = [1]] = "OneArr";
FancyType[FancyType["TwoArr"] = [2, 2]] = "TwoArr";
enumValues.forEach(v=> console.log(v))
//A
//B
enum AdditionToSourceEnum {
value3 = <any>'value3',
value4 = <any>'value4'
}
console.log(TestEnum.value1);
console.log(TestEnum.value2 === <any>'value2');
console.log(check(TestEnum.value2));
console.log(check(TestEnum.value3));
class Enum {
constructor(protected value: string) {}
public toString() {
return String(this.value);
console.log(value1 + 'hello');
console.log(value1.toString() === 'value1');
console.log(value1.is('value1'));
console.log(!TestEnum.value3.is(TestEnum.value3));
console.log(check(TestEnum.value2));
// this works but perhaps your TSLint would complain
// attention! does not work with ===
// use .is() instead
console.log(TestEnum.value1 == <any>'value1');
In TypeScript, every parameter is assumed to be required by the function. You can add a ? at the end of a
parameter name to set it as optional.
Default Parameters
If the user passes undefined or doesn't specify an argument, the default value will be assigned. These are called
default-initialized parameters.
For example, "Smith" is the default value for the lastName parameter.
interface IConstructor {
new();
Or with parameters:
interface INumberConstructor {
new(num: number);
}
If we want to receive a simple function and not a constructor it's almost the same:
interface IFunction {
(): void;
}
Or with parameters:
interface INumberFunction {
(num: number): string;
}
whatTime(1,30) //'1:30'
whatTime('1',30) //'1:30'
whatTime(1,'30') //'1:30'
whatTime('1','30') //'1:30'
TypeScript treats these parameters as a single type that is a union of the other types, so your function must be able
to handle parameters of any type that is in the union.
function addTen(start:number|string):number{
if(typeof number === 'string'){
return parseInt(number)+10;
}else{
else return number+10;
}
}
function multiply(a, b) {
return a * b;
}
Anonymous functions
The class support in TypeScript is similar to that of languages like Java and C#, in that classes may inherit from
other classes, while objects are instantiated as class instances.
Also similar to those languages, TypeScript classes may implement interfaces or make use of generics.
move() {
this.position += this.speed;
}
moreInfo() {
return `This is a car located at ${this.position} and going ${this.speed}mph!`;
}
}
Abstract classes are base classes from which other classes can extend. They cannot be instantiated themselves (i.e.
you cannot do new Machine("Konda")).
For this reason, abstract classes can conceptually be considered a combination of an interface and a class.
move() {
this.position += this.speed;
}
}
In this example, we declare a simple class Car. The class has three members: a private property speed, a public
property position and a public method move. Note that each member is public by default. That's why move() is
public, even if we didn't use the public keyword.
move() {
this.position += this.speed;
}
}
move() {
// start moving around :-)
super.move();
super.move();
}
}
This examples shows how to create a very simple subclass of the Car class using the extends keyword. The
SelfDrivingCar class overrides the move() method and uses the base class implementation using super.
One of the best things in TypeScript, is automatic assignment of constructor parameters to the relevant property.
class Car {
public position: number;
protected speed: number;
move() {
this.position += this.speed;
class Car {
constructor(public position: number, protected speed: number) {}
move() {
this.position += this.speed;
}
}
And both of them will be transpiled from TypeScript (design time and compile time) to JavaScript with same result,
but writing significantly less code:
Constructors of derived classes have to call the base class constructor with super().
class Car {
public position: number = 0;
private _speed: number = 42;
private _MAX_SPEED = 100
move() {
this.position += this._speed;
}
TypeScript source
class SomeClass {
constructor () {
SomeClass.SomeStaticValue = SomeClass.getGoodbye();
this.someMemberValue = this.getFortyTwo();
this.somePrivateValue = this.getTrue();
}
JavaScript source
Observations
interface String {
toCamelCase(): string;
}
// Return target
return target;
@addMetadata
class Person {
private _name: string;
public constructor(name: string) {
this._name = name;
}
public greet() {
return this._name;
}
}
console.log(getMetadataFromClass(Person));
The decorator is applied when the class is declared not when we create instances of the class. This means that the
metadata is shared across all the instances of a class:
console.log(getMetadataFromInstance(person1));
console.log(getMetadataFromInstance(person2));
// Add metadata
target.__customMetadata = metadata;
// Return target
return target;
}
}
The addMetadata takes some arguments used as configuration and then returns an unnamed function which is the
actual decorator. In the decorator we can access the arguments because there is a closure in place.
console.log(getMetadataFromInstance(Person));
{ guid: "417c6ec7-ec05-4954-a3c6-73a0d7f9f5bf" }
function log<T>(target: T) {
// Return target
return target;
The primary benefit of using interfaces, is that it allows one to use objects of different types in a polymorphic way.
This is because any class implementing the interface has at least those fields and functions.
interface IPerson {
name: string;
age: number;
breath(): void;
}
And we want to create more specific interface that has the same properties of the person, we can do it using the
extends keyword:
interface ISampleClassInterface {
sampleVariable: string;
sampleMethod(): void;
optionalVariable?: string;
}
constructor() {
this.sampleVariable = 'string value';
this.answerToLifeTheUniverseAndEverything = 42;
}
The example shows how to create an interface ISampleClassInterface and a class SampleClass that implements
the interface.
interface Connector{
doConnect(): boolean;
}
This is connector interface. Now we will implement that for Wifi communication.
Here we have developed our concrete class named WifiConnector that has its own implementation. This is now
type Connector.
Now we are creating our System that has a component Connector. This is called dependency injection.
constructor(private connector: Connector) this line is very important here. Connector is an interface and must
have doConnect(). As Connector is an interface this class System has much more flexibility. We can pass any Type
which has implemented Connector interface. In future developer achieves more flexibility. For example, now
developer want to add Bluetooth Connection module:
See that Wifi and Bluetooth have its own implementation. Their own different way to connect. However, hence both
have implemented Type Connector the are now Type Connector. So that we can pass any of those to System class
as the constructor parameter. This is called polymorphism. The class System is now not aware of whether it is
Bluetooth / Wifi even we can add another Communication module like Infrared, Bluetooth5 and whatsoever by just
implementing Connector interface.
This is called Duck typing. Connector type is now dynamic as doConnect() is just a placeholder and developer
implement this as his/her own.
interface IEvents<T> {
list: T[];
emit(event: T): void;
getAll(): T[];
}
Here, you can see that our two interfaces take some generic parameters, T and U.
list: T[];
constructor() {
this.list = [];
}
getAll(): T[] {
return this.list;
}
In our example, the State class will handle a generic status by using IStatus<T>. In this way, the interface
Our State class is typed as IStatus<Code>. In this way, we are able to pass more complex type to our emit method.
As you can see, generic interfaces can be a very useful tool for statically typed code.
interface JQuery {
pluginFunctionThatDoesNothing(): void;
The compiler will merge all declarations with the same name into one - see declaration merging for more details.
interface IKickable {
kick(distance: number): void;
}
class Ball {
kick(distance: number): void {
console.log("Kicked", distance, "meters!");
}
So even if Ball doesn't explicitly implement IKickable, a Ball instance may be assigned to (and manipulated as) an
IKickable, even when the type is specified.
You have this simple function that checks if two pets are compatible with each other...
checkCompatible(petOne, petTwo) {
if (petOne.species === petTwo.species &&
Math.abs(petOne.age - petTwo.age) <= 5) {
return true;
}
}
This is completely functional code, but it would be far too easy for someone, especially other people working on
this application who didn't write this function, to be unaware that they are supposed to pass it objects with 'species'
and 'age' properties. They may mistakenly try checkCompatible(petOne.species, petTwo.species) and then be
left to figure out the errors thrown when the function tries to access petOne.species.species or petOne.species.age!
One way we can prevent this from happening is to specify the properties we want on the pet parameters:
checkCompatible(petOne: {species: string, age: number}, petTwo: {species: string, age: number}) {
//...
}
In this case, TypeScript will make sure everything passed to the function has 'species' and 'age' properties (it is okay
if they have additional properties), but this is a bit of an unwieldy solution, even with only two properties specified.
With interfaces, there is a better way!
interface Pet {
species: string;
age: number;
//We can add more properties if we choose.
}
Now all we have to do is specify the type of our parameters as our new interface, like so...
... and TypeScript will make sure that the parameters passed to our function contain the properties specified in the
Pet interface!
clone(): IResult<T>;
}
let x = { a: 1, b: 2, c: 3, d: 4 };
assign(x, { b: 10, d: 20 });
assign(x, { e: 0 }); // Error
interface IRunnable {
run(): void;
}
interface IRunnble<U> {
run(): U;
}
interface IRunnble<V> {
run(parameter: U): V;
}
interface IRunner {
runSafe<T extends IRunnable>(runnable: T): void;
}
In classes:
Simple functions:
TypeScript 2.0 adds support for strict null checks. If you set --strictNullChecks when running tsc (or set this flag
in your tsconfig.json), then types no longer permit null:
With a proper guard, the code type checks and runs correctly:
If the function returns true, TypeScript will narrow the type to DesiredType in any block guarded by a call to the
function.
A guard's function type predicate (the foo is Bar in the function return type position) is used at compile time to
narrow types, the function body is used at runtime. The type predicate and function must agree, or your code won't
work.
Type guard functions don't have to use typeof or instanceof, they can use more complicated logic.
For example, this code determines if you've got a jQuery object by checking for its version string.
function example(foo) {
if (isJQuery(foo)) {
// foo is typed JQuery here
foo.eq(0);
}
}
class Pet { }
class Dog extends Pet {
bark() {
console.log("woof");
}
}
class Cat extends Pet {
purr() {
console.log("meow");
}
}
example(new Dog());
example(new Cat());
prints
woof
meow
to the console.
Unlike instanceof, typeof will work with a variable of any type. In the example below, foo could be typed as number
| string without issue.
example(23);
example("foo");
prints
123
not a number: foo
class Flies {
fly() {
alert('Is it a bird? Is it a plane?');
}
}
class Climbs {
climb() {
alert('My spider-sense is tingling.');
}
}
class Bulletproof {
deflect() {
alert('My wings are a shield of steel.');
}
}
// place in jquery.d.ts
declare let $: any;
export default $;
And then in any file in your project, you can import this definition with:
If the library has multiple top-level variables, export and import by name instead:
// place in jquery.d.ts
declare module "jquery" {
let $: any;
let jQuery: any;
export { $ };
export { jQuery };
}
$.doThing();
jQuery.doOtherThing();
If jQuery didn't have type declarations (it does), you could put
Anything imported from the declared module (like $ and jQuery) above will be of type any
tsc -v
Thank you.
Thank you,
Using API
var browserify = require("browserify");
var tsify = require("tsify");
browserify()
.add("main.ts")
.plugin("tsify", { noImplicitAny: true })
.bundle()
.pipe(process.stdout);
Basic webpack.config.js
webpack 2.x, 3.x
module.exports = {
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
module: {
rules: [
{
// Set up ts-loader for .ts/.tsx files and exclude any imports from node_modules.
test: /\.tsx?$/,
loaders: ['ts-loader'],
exclude: /node_modules/
}
]
},
entry: [
// Set index.tsx as application entry point.
'./index.tsx'
],
output: {
filename: "bundle.js"
}
};
webpack 1.x
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js"
Alternatives:
awesome-typescript-loader
Basic Gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
ts: {
default : {
src: ["**/*.ts", "!node_modules/**/*.ts"]
}
}
});
grunt.loadNpmTasks("grunt-ts");
grunt.registerTask("default", ["ts"]);
};
Basic gulpfile.js
var gulp = require("gulp");
var ts = require("gulp-typescript");
gulp.task("default", function () {
var tsResult = gulp.src("src/*.ts")
.pipe(ts({
noImplicitAny: true,
out: "output.js"
}));
return tsResult.js.pipe(gulp.dest("built/local"));
});
class Flies {
fly() {
alert('Is it a bird? Is it a plane?');
}
}
class Climbs {
climb() {
alert('My spider-sense is tingling.');
}
}
class Bulletproof {
deflect() {
alert('My wings are a shield of steel.');
}
}
// place in jquery.d.ts
declare let $: any;
export default $;
And then in any file in your project, you can import this definition with:
If the library has multiple top-level variables, export and import by name instead:
// place in jquery.d.ts
declare module "jquery" {
let $: any;
let jQuery: any;
export { $ };
export { jQuery };
}
$.doThing();
jQuery.doOtherThing();
If jQuery didn't have type declarations (it does), you could put
Anything imported from the declared module (like $ and jQuery) above will be of type any
tsc -v
Thank you.
templates/myModuleComponent.html
<div class="my-module-component">
{{$ctrl.someContent}}
</div>
controller/MyModuleController.ts
services/MyModuleService.ts
constructor() {
}
somewhere.html
<my-module-component></my-module-component>
Thank you,
Using API
var browserify = require("browserify");
var tsify = require("tsify");
browserify()
.add("main.ts")
.plugin("tsify", { noImplicitAny: true })
.bundle()
.pipe(process.stdout);
Basic webpack.config.js
webpack 2.x, 3.x
module.exports = {
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
module: {
rules: [
{
// Set up ts-loader for .ts/.tsx files and exclude any imports from node_modules.
test: /\.tsx?$/,
loaders: ['ts-loader'],
exclude: /node_modules/
}
]
},
entry: [
// Set index.tsx as application entry point.
'./index.tsx'
],
output: {
filename: "bundle.js"
}
};
webpack 1.x
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js"
Alternatives:
awesome-typescript-loader
Basic Gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
ts: {
default : {
src: ["**/*.ts", "!node_modules/**/*.ts"]
}
}
});
grunt.loadNpmTasks("grunt-ts");
grunt.registerTask("default", ["ts"]);
};
Basic gulpfile.js
var gulp = require("gulp");
var ts = require("gulp-typescript");
gulp.task("default", function () {
var tsResult = gulp.src("src/*.ts")
.pipe(ts({
noImplicitAny: true,
out: "output.js"
}));
return tsResult.js.pipe(gulp.dest("built/local"));
});
gulp.task("default", function () {
var tsResult = tsProject.src()
.pipe(tsProject());
return tsResult.js.pipe(gulp.dest('release'));
});
Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Micr
osoft.TypeScript.Default.props"
Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeS
cript\Microsoft.TypeScript.Default.props')" />
Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Micr
osoft.TypeScript.targets"
Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeS
cript\Microsoft.TypeScript.targets')" />
</Project>
More details about defining MSBuild compiler options: Setting Compiler Options in MSBuild projects
webpack.config.js
module.exports = {
entry: {
app: ['./src/'],
},
output: {
path: __dirname,
filename: './dist/[name].js',
},
resolve: {
extensions: ['', '.js', '.ts'],
},
module: {
loaders: [{
test: /\.ts(x)$/, loaders: ['ts-loader'], exclude: /node_modules/
}],
}
};
Using TypeScript with RequireJS requires configuration of tsconfig.json, and including an snippet in any HTML file.
Compiler will traduce imports from the syntax of TypeScript to RequireJS' format.
interface IMyDirectiveController {
// specify exposed controller methods and properties here
getUrl(): string;
}
/*
* Outer injections, for run once control.
* For example we have all templates in one value, and we want to use it.
*/
export function myDirective(templatesUrl: ITemplates): ng.IDirective {
return {
controller: MyDirectiveController,
controllerAs: "vm",
},
replace: true,
require: "ngModel",
restrict: "A",
templateUrl: templatesUrl.myDirective,
};
}
myDirective.$inject = [
Templates.prototype.slug,
];
// You can place this in some bootstrap file, or have them at the same file
angular.module("myApp").
directive(myDirective.prototype.slug, myDirective);
},
replace: true,
require: "ngModel",
restrict: "A",
templateUrl: templatesUrl.myDirective,
};
}
// Using slug naming across the projects simplifies change of the directive name
myDirective.prototype.slug = "myDirective";
// You can place this in some bootstrap file, or have them at the same file
angular.module("myApp").
directive(myDirective.prototype.slug, [
Templates.prototype.slug,
myDirective
]);
myModule.ts
angular
.module("myModule", [])
.component("myModuleComponent", new MyModuleComponent())
.service("myModuleService", MyModuleService);
components/myModuleComponent.ts
templates/myModuleComponent.html
<div class="my-module-component">
{{$ctrl.someContent}}
</div>
controller/MyModuleController.ts
services/MyModuleService.ts
constructor() {
}
somewhere.html
<my-module-component></my-module-component>
NOTE: this will install typescript 2.0.0 compiler which is not released yet.
<!doctype html>
<html>
<head>
<title>Hello World in TypeScript</title>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="config.js"></script>
<script>
window.addEventListener('load', function() {
System.import('./hello.ts').then(function(hello) {
document.body.innerHTML = hello.greeter('World');
});
});
</script>
</head>
<body>
</body>
</html>
System.config({
packages: {
"plugin-typescript": {
"main": "plugin.js"
},
"typescript": {
"main": "lib/typescript.js",
"meta": {
"lib/typescript.js": {
"exports": "ts"
}
}
}
NOTE: if you don't want type checking, remove loader: "plugin-typescript" and typescriptOptions from
config.js. Also note that it will never check javascript code, in particular code in the <script> tag in html example.
Test it
node build.js
Use it in production
hello-production.html file:
<!doctype html>
<html>
<head>
<title>Hello World in TypeScript</title>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="config.js"></script>
<script src="hello.js"></script>
</head>
<body>
</body>
</html>
//helloMessage.tsx:
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
But in order to make full use of TypeScript's main feature (static type checking) you must do a couple things:
//helloMessage.tsx:
class HelloMessage extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
interface Props {
name:string;
optionalParam?:number;
}
interface State {
//empty in our case
}
Now TypeScript will display an error if the programmer forgets to pass props. Or if trying to pass in props that are
not defined in the interface.
Linking TypeScript allows ts-loader to use your global installation of TypeScript instead of needing a
separate local copy typescript doc
{
"compilerOptions": {
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es5",
"jsx": "react"
}
}
module.exports = {
entry: "<path to entry point>",// for example ./src/helloMessage.tsx
output: {
filename: "<path to bundle file>", // for example ./dist/bundle.js
},
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
loaders: [
// All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
{test: /\.tsx?$/, loader: "ts-loader"}
],
// When importing a module whose path matches one of the following, just
// assume a corresponding global variable exists and use that instead.
// This is important because it allows us to avoid bundling all of our
// dependencies, which allows browsers to cache those libraries between builds.
externals: {
"react": "React",
"react-dom": "ReactDOM"
},
};
To enforce this rules, include tslint in your build process and check your code before compiling it with tsc.
{
"rules": {
// TypeScript Specific
"member-access": true, // Requires explicit visibility declarations for class members.
"no-any": true, // Disallows usages of any as a type declaration.
// Functionality
"label-position": true, // Only allows labels in sensible locations.
"no-bitwise": true, // Disallows bitwise operators.
"no-eval": true, // Disallows eval function invocations.
"no-null-keyword": true, // Disallows use of the null keyword literal.
"no-unsafe-finally": true, // Disallows control flow statements, such as return, continue,
break and throws in finally blocks.
"no-var-keyword": true, // Disallows usage of the var keyword.
"radix": true, // Requires the radix parameter to be specified when calling parseInt.
"triple-equals": true, // Requires === and !== in place of == and !=.
"use-isnan": true, // Enforces use of the isNaN() function to check for NaN references instead
of a comparison to the NaN constant.
// Style
"class-name": true, // Enforces PascalCased class and interface names.
"interface-name": [ true, "never-prefix" ], // Requires interface names to begin with a capital
‘I’
"no-angle-bracket-type-assertion": true, // Requires the use of as Type for type assertions
instead of <Type>.
"one-variable-per-declaration": true, // Disallows multiple variable definitions in the same
declaration statement.
"quotemark": [ true, "double", "avoid-escape" ], // Requires double quotes for string literals.
"semicolon": [ true, "always" ], // Enforces consistent semicolon usage at the end of every
statement.
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"] // Checks
variable names for various errors. Disallows the use of certain TypeScript keywords (any, Number,
number, String, string, Boolean, boolean, undefined) as variable or parameter. Allows only camelCased
or UPPER_CASED variable names. Allows underscores at the beginning (only has an effect if “check-
format” specified).
}
}
Tslint is configured via file tslint.json. To initialize default configuration run command
tslint filename.ts
Yeoman generator supports all these presets and can be extends also:
generator-tslint
{
"rules": {
"no-any": true,
"curly": true,
"quotemark": [true, "double"]
}
}
tslint:recommended is a stable, somewhat opinionated set of rules which we encourage for general
TypeScript programming. This configuration follows semver, so it will not have breaking changes across
minor or patch releases.
tslint:latest extends tslint:recommended and is continuously updated to include configuration for the
latest rules in every TSLint release. Using this config may introduce breaking changes across minor
releases as new rules are enabled which cause lint failures in your code. When TSLint reaches a major
version bump, tslint:recommended will be updated to be identical to tslint:latest.
{
"extends": "tslint:recommended"
}
One can then overwrite rules from that preset via rules, e.g. for node developers it made sense to set no-console
to false:
{
"extends": "tslint:recommended",
"rules": {
"no-console": false
}
}
Initializing a TypeScript project, or better put tsconfig.json file, can be done through the following command:
tsc --init
As of TypeScript v2.3.0 and higher this will create the following tsconfig.json by default:
{
"compilerOptions": {
/* Basic Options */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default),
'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'commonjs', 'amd',
'system', 'umd' or 'es2015'. */
// "lib": [], /* Specify library files to be included in the
compilation: */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-
native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to
control the output directory structure with --outDir. */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of',
spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to
'ts.transpileModule'). */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function
return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch
statement. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type
metadata for decorators. */
}
}
Most, if not all, options are generated automatically with only the bare necessities left uncommented.
Older versions of TypeScript, like for example v2.0.x and lower, would generate a tsconfig.json like this:
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false
}
}
{
"compilerOptions": {
"alwaysStrict": true, // Parse in strict mode and emit "use strict" for each source file.
// If you have wrong casing in referenced files e.g. the filename is Global.ts and you have a ///
<reference path="global.ts" /> to reference this file, then this can cause to unexpected errors.
Visite: http://stackoverflow.com/questions/36628612/typescript-transpiler-casing-issue
"forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the
same file.
"noImplicitAny": true, // Raise error on expressions and declarations with an implied "any"
type.
"noImplicitThis": true, // Raise error on this expressions with an implied "any" type.
"strictNullChecks": true, // The null and undefined values are not in the domain of every type
and are only assignable to themselves and any.
Not enough? If you are a hard coder and want more, then you may be interested to check your TypeScript files with
tslint before compiling it with tsc. Check how to configure tslint for even stricter code.
{
"compileOnSave": true,
"compilerOptions": {
...
},
"exclude": [
...
]
}
This feature is available since TypeScript 1.8.4 and onward, but needs to be directly supported by IDE's. Currently,
examples of supported IDE's are:
//Leading comment
{
"compilerOptions": {
//this is a line comment
"module": "commonjs", //eol line comment
"target" /*inline block*/ : "es5",
/* This is a
block
comment */
}
}
This is usually just syntax sugar as the constant enums are inlined in compiled JavaScript.
compiles to
var something = 0;
Although the performance benefit from inlining, you may prefer to keep enums even if constant (ie: you may wish
readability on development code), to do this you have to set in tsconfig.json the preserveConstEnums clause into
the compilerOptions to true.
{
"compilerOptions": {
"preserveConstEnums" = true,
...
},
"exclude": [
...
]
}
By this way the previous example would be compiled as any other enums, as shown in following snippet.
var Tristate;
(function (Tristate) {
Tristate[Tristate["True"] = 0] = "True";
Tristate[Tristate["False"] = 1] = "False";
Tristate[Tristate["Unknown"] = 2] = "Unknown";
})(Tristate || (Tristate = {}));
Transpile to JavaScript, run in node and use mappings to link back to the TypeScript source files
or
This article describes both ways using Visual Studio Code and WebStorm. All examples presume that your main file
is index.ts.
Right click on the script and select Create 'test:idea'... and confirm with 'OK' to create the debug configuration:
npm i ts-node
{
"version": "0.2.0",
"configurations": [
{
"type": "node2",
"request": "launch",
"name": "Launch Program",
"runtimeExecutable": "npm",
"windows": {
"runtimeExecutable": "npm.cmd"
},
"runtimeArgs": [
"run-script",
"start:debug"
],
"cwd": "${workspaceRoot}/server",
"outFiles": [],
"port": 5858,
"sourceMaps": true
}
]
}
"sourceMap": true,
to generate mappings alongside with js-files from the TypeScript sources using the tsc command.
The launch.json file:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceRoot}\\index.js",
"cwd": "${workspaceRoot}",
"outFiles": [],
"sourceMaps": true
}
]
}
This starts node with the generated index.js (if your main file is index.ts) file and the debugger in Visual Studio Code
which halts on breakpoints and resolves variable values within your TypeScript code.
To use tape with TypeScript you need to install ts-node as global package, to do this run command
//math.test.ts
import * as test from "tape";
t.end();
});
TAP version 13
# Math test
ok 1 should be equal
ok 2 should be truthy
1..2
# tests 2
# pass 2
# ok
You can run multiple test files at once using path wildcards. To execute all TypeScript tests in tests directory run
command
To make jest work with TypeScript you need to add configuration to package.json
//package.json
{
...
"jest": {
"transform": {
".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"moduleFileExtensions": ["ts", "tsx", "js"]
}
}
//fizzBuzz.ts
export function fizzBuzz(n: number): string {
let output = "";
for (let i = 1; i <= n; i++) {
if (i % 5 && i % 3) {
output += i + ' ';
}
if (i % 3 === 0) {
output += 'Fizz ';
}
if (i % 5 === 0) {
output += 'Buzz ';
}
}
return output;
}
//FizzBuzz.test.ts
/// <reference types="jest" />
PASS ./fizzBuzz.test.ts
✓ FizzBuzz test (3ms)
Code coverage
To use code coverage with TypeScript you need to add another configuration line to package.json.
{
...
"jest": {
...
"testResultsProcessor": "<rootDir>/node_modules/ts-jest/coverageprocessor.js"
}
}
jest --coverage
PASS ./fizzBuzz.test.ts
✓ FizzBuzz test (3ms)
-------------|----------|----------|----------|----------|----------------|
File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |
-------------|----------|----------|----------|----------|----------------|
All files | 92.31 | 87.5 | 100 | 91.67 | |
fizzBuzz.ts | 92.31 | 87.5 | 100 | 91.67 | 13 |
-------------|----------|----------|----------|----------|----------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.857s
Ran all test suites.
jest also created folder coverage which contains coverage report in various formats, including user friendly html
report in coverage/lcov-report/index.html
export SomeModuleTests {
@Test()
public statusShouldBeTrueByDefault() {
let instance = new SomeModule();
Expect(instance.status).toBe(true);
}
Expect(instance.name).toBe(null);
}
@TestCase("first name")
@TestCase("apples")
public shouldSetNameCorrectly(name: string) {
let instance = new SomeModule();
instance.setName(name);
Expect(instance.name).toBe(name);
}
chai.use(chaiImmutable);
expect(Set.of(1,2,3)).to.include(2);
expect(Set.of(1,2,3)).to.include(5);
})
})