summaryrefslogtreecommitdiffhomepage
path: root/typescript.html.markdown
diff options
context:
space:
mode:
Diffstat (limited to 'typescript.html.markdown')
-rw-r--r--typescript.html.markdown187
1 files changed, 148 insertions, 39 deletions
diff --git a/typescript.html.markdown b/typescript.html.markdown
index 1d712369..f7a41ce1 100644
--- a/typescript.html.markdown
+++ b/typescript.html.markdown
@@ -5,33 +5,49 @@ contributors:
filename: learntypescript.ts
---
-TypeScript is a language that aims at easing development of large scale applications written in JavaScript.
-TypeScript adds common concepts such as classes, modules, interfaces, generics and (optional) static typing to JavaScript.
-It is a superset of JavaScript: all JavaScript code is valid TypeScript code so it can be added seamlessly to any project. The TypeScript compiler emits JavaScript.
+TypeScript is a language that aims at easing development of large scale
+applications written in JavaScript. TypeScript adds common concepts such as
+classes, modules, interfaces, generics and (optional) static typing to
+JavaScript. It is a superset of JavaScript: all JavaScript code is valid
+TypeScript code so it can be added seamlessly to any project. The TypeScript
+compiler emits JavaScript.
-This article will focus only on TypeScript extra syntax, as opposed to [JavaScript](javascript.html.markdown).
+This article will focus only on TypeScript extra syntax, as opposed to
+[JavaScript](/docs/javascript).
-To test TypeScript's compiler, head to the [Playground] (http://www.typescriptlang.org/Playground) where you will be able to type code, have auto completion and directly see the emitted JavaScript.
+To test TypeScript's compiler, head to the
+[Playground](https://www.typescriptlang.org/play) where you will be able
+to type code, have auto completion and directly see the emitted JavaScript.
-```js
+```ts
// There are 3 basic types in TypeScript
-var isDone: boolean = false;
-var lines: number = 42;
-var name: string = "Anders";
+let isDone: boolean = false;
+let lines: number = 42;
+let name: string = "Anders";
+
+// But you can omit the type annotation if the variables are derived
+// from explicit literals
+let isDone = false;
+let lines = 42;
+let name = "Anders";
// When it's impossible to know, there is the "Any" type
-var notSure: any = 4;
+let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
+// Use const keyword for constants
+const numLivesForCat = 9;
+numLivesForCat = 1; // Error
+
// For collections, there are typed arrays and generic arrays
-var list: number[] = [1, 2, 3];
+let list: number[] = [1, 2, 3];
// Alternatively, using the generic array type
-var list: Array<number> = [1, 2, 3];
+let list: Array<number> = [1, 2, 3];
// For enumerations:
-enum Color {Red, Green, Blue};
-var c: Color = Color.Green;
+enum Color { Red, Green, Blue };
+let c: Color = Color.Green;
// Lastly, "void" is used in the special case of a function returning nothing
function bigHorribleAlert(): void {
@@ -41,16 +57,18 @@ function bigHorribleAlert(): void {
// Functions are first class citizens, support the lambda "fat arrow" syntax and
// use type inference
-// The following are equivalent, the same signature will be infered by the
+// The following are equivalent, the same signature will be inferred by the
// compiler, and same JavaScript will be emitted
-var f1 = function(i: number): number { return i * i; }
+let f1 = function (i: number): number { return i * i; }
// Return type inferred
-var f2 = function(i: number) { return i * i; }
-var f3 = (i: number): number => { return i * i; }
-// Return type inferred
-var f4 = (i: number) => { return i * i; }
-// Return type inferred, one-liner means no return keyword needed
-var f5 = (i: number) => i * i;
+let f2 = function (i: number) { return i * i; }
+// "Fat arrow" syntax
+let f3 = (i: number): number => { return i * i; }
+// "Fat arrow" syntax with return type inferred
+let f4 = (i: number) => { return i * i; }
+// "Fat arrow" syntax with return type inferred, braceless means no return
+// keyword needed
+let f5 = (i: number) => i * i;
// Interfaces are structural, anything that has the properties is compliant with
// the interface
@@ -64,19 +82,19 @@ interface Person {
// Object that implements the "Person" interface
// Can be treated as a Person since it has the name and move properties
-var p: Person = { name: "Bobby", move: () => {} };
+let p: Person = { name: "Bobby", move: () => { } };
// Objects that have the optional property:
-var validPerson: Person = { name: "Bobby", age: 42, move: () => {} };
+let validPerson: Person = { name: "Bobby", age: 42, move: () => { } };
// Is not a person because age is not a number
-var invalidPerson: Person = { name: "Bobby", age: true };
+let invalidPerson: Person = { name: "Bobby", age: true };
// Interfaces can also describe a function type
interface SearchFunc {
(source: string, subString: string): boolean;
}
// Only the parameters' types are important, names are not important.
-var mySearch: SearchFunc;
-mySearch = function(src: string, sub: string) {
+let mySearch: SearchFunc;
+mySearch = function (src: string, sub: string) {
return src.search(sub) != -1;
}
@@ -96,14 +114,21 @@ class Point {
}
// Functions
- dist() { return Math.sqrt(this.x * this.x + this.y * this.y); }
+ dist(): number { return Math.sqrt(this.x * this.x + this.y * this.y); }
// Static members
static origin = new Point(0, 0);
}
-var p1 = new Point(10 ,20);
-var p2 = new Point(25); //y will be 0
+// Classes can be explicitly marked as implementing an interface.
+// Any missing properties will then cause an error at compile-time.
+class PointPerson implements Person {
+ name: string
+ move() {}
+}
+
+let p1 = new Point(10, 20);
+let p2 = new Point(25); //y will be 0
// Inheritance
class Point3D extends Point {
@@ -112,8 +137,8 @@ class Point3D extends Point {
}
// Overwrite
- dist() {
- var d = super.dist();
+ dist(): number {
+ let d = super.dist();
return Math.sqrt(d * d + this.z * this.z);
}
}
@@ -129,12 +154,12 @@ module Geometry {
}
}
-var s1 = new Geometry.Square(5);
+let s1 = new Geometry.Square(5);
// Local alias for referencing a module
import G = Geometry;
-var s2 = new G.Square(10);
+let s2 = new G.Square(10);
// Generics
// Classes
@@ -150,23 +175,107 @@ interface Pair<T> {
}
// And functions
-var pairToTuple = function<T>(p: Pair<T>) {
+let pairToTuple = function <T>(p: Pair<T>) {
return new Tuple(p.item1, p.item2);
};
-var tuple = pairToTuple({ item1:"hello", item2:"world"});
+let tuple = pairToTuple({ item1: "hello", item2: "world" });
// Including references to a definition file:
/// <reference path="jquery.d.ts" />
// Template Strings (strings that use backticks)
// String Interpolation with Template Strings
-var name = 'Tyrone';
-var greeting = `Hi ${name}, how are you?`
+let name = 'Tyrone';
+let greeting = `Hi ${name}, how are you?`
// Multiline Strings with Template Strings
-var multiline = `This is an example
+let multiline = `This is an example
of a multiline string`;
+// READONLY: New Feature in TypeScript 3.1
+interface Person {
+ readonly name: string;
+ readonly age: number;
+}
+
+var p1: Person = { name: "Tyrone", age: 42 };
+p1.age = 25; // Error, p1.age is read-only
+
+var p2 = { name: "John", age: 60 };
+var p3: Person = p2; // Ok, read-only alias for p2
+p3.age = 35; // Error, p3.age is read-only
+p2.age = 45; // Ok, but also changes p3.age because of aliasing
+
+class Car {
+ readonly make: string;
+ readonly model: string;
+ readonly year = 2018;
+
+ constructor() {
+ this.make = "Unknown Make"; // Assignment permitted in constructor
+ this.model = "Unknown Model"; // Assignment permitted in constructor
+ }
+}
+
+let numbers: Array<number> = [0, 1, 2, 3, 4];
+let moreNumbers: ReadonlyArray<number> = numbers;
+moreNumbers[5] = 5; // Error, elements are read-only
+moreNumbers.push(5); // Error, no push method (because it mutates array)
+moreNumbers.length = 3; // Error, length is read-only
+numbers = moreNumbers; // Error, mutating methods are missing
+
+// Tagged Union Types for modelling state that can be in one of many shapes
+type State =
+ | { type: "loading" }
+ | { type: "success", value: number }
+ | { type: "error", message: string };
+
+declare const state: State;
+if (state.type === "success") {
+ console.log(state.value);
+} else if (state.type === "error") {
+ console.error(state.message);
+}
+
+// Iterators and Generators
+
+// for..of statement
+// iterate over the list of values on the object being iterated
+let arrayOfAnyType = [1, "string", false];
+for (const val of arrayOfAnyType) {
+ console.log(val); // 1, "string", false
+}
+
+let list = [4, 5, 6];
+for (const i of list) {
+ console.log(i); // 4, 5, 6
+}
+
+// for..in statement
+// iterate over the list of keys on the object being iterated
+for (const i in list) {
+ console.log(i); // 0, 1, 2
+}
+
+// Type Assertion
+
+let foo = {} // Creating foo as an empty object
+foo.bar = 123 // Error: property 'bar' does not exist on `{}`
+foo.baz = 'hello world' // Error: property 'baz' does not exist on `{}`
+
+// Because the inferred type of foo is `{}` (an object with 0 properties), you
+// are not allowed to add bar and baz to it. However with type assertion,
+// the following will pass:
+
+interface Foo {
+ bar: number;
+ baz: string;
+}
+
+let foo = {} as Foo; // Type assertion here
+foo.bar = 123;
+foo.baz = 'hello world'
+
```
## Further Reading