Skip to content

Instantly share code, notes, and snippets.

@artieziff
Last active November 8, 2017 22:06
Show Gist options
  • Save artieziff/b0b161f52ec60fbabddb0f316ece5f68 to your computer and use it in GitHub Desktop.
Save artieziff/b0b161f52ec60fbabddb0f316ece5f68 to your computer and use it in GitHub Desktop.

TYPESCRIPT

Installing typescript

npm install -g typescript

Transpile command

tsc ./filepath.ts

Watch file changes

tsc -w ./filepath.ts

TYPESCRIPT CONFIGURATION FILE

Add a file called "tsconfig.json":

{
	"compilerOptions": {
		"target": "es5"
	}
}

If this file exists you can type:

tsc -w

and Typescript will know which files to compile

ES6 LANGUAGE FEATURES

OPTIONAL PARAMETERS

function countdown (initial, final = 0, interval= 1) {

	var current = initial;
	
	while (current > final) {
	
		container.innerHTML = current
		current-=interval;
		
	}
	
}

TEMPLATE LITERALS

Template literals are string literals allowing embedded expressions

var todo = {

	id: 123,
	name: "Pickup drycleaning",
	completed: true
	
};

var displayName = `
	<div todo="${todo.id}" class="list-group-item">
		<i class="${todo.completed ? '': 'hidden'} text-success"></i>
		<span class="name">${todo.name}</span>
	</div>
`;

LET AND CONST

Let - Declare a block scope variable

for (var i = 0; i<=5; i++) {

	let counter = i;
	
}

Const - Create a read-only reference to a value

const id = 'A8D76ASDADASD98';

FOR...OF LOOPS

Used to iterate iterable objects. Similar to the "For in" loop but iterates values instead of keys.

for (let value of array) {

	console.log(value);
	
}

ARROW FUNCTIONS (LAMBDAS)

Use curly braces to group statements

var fn = (param1) => {

	var square = param1 * param1;
	return square;
	
}

If just one parameter is used you can write it without parenthesis. When only one statement is used that becomes the implicit return.

var fn = param 1 => param1*param1; //Returns param1*param1

If you want the function to return an object you need to use parenthesis.

var fn = param1 => ({value: param1*param1});

DESTRUCTURING

Assign values to multiple variables from a single object with a single statement.

ES6

var array = [123, 'Pickup drycleaning.', true];
var [id, title, completed] = array;
var todo = {

	id: 123,
	name: "Pickup drycleaning",
	completed: true
	
};

var {id, name, completed} = todo;

ES5

var array = [123, 'Pickup drycleaning.', true];
var id = array[0], title = array[1], completed = array[2];
var todo = {

	id: 123,
	name: "Pickup drycleaning",
	completed: true
	
};

var id = todo.id, title = todo.title, completed = todo.completed;

Usage example

function countdown ({

	initial,
	final: final = 0,
	interval: interval = 1,
	initial: current
	
}) {

	while (current > final) {
	
		container.innerHTML = current
		current-=interval;
		
	}
	
}

SPREAD OPERATOR

Can be used to expand an iterable object when multiple items are expected.

function calculate (action, ...values) {

	var total = 0;
	
	for (var value of values) {
	
		switch (action) {
		
			case 'add':
				total+= values;
				break;
				
			case 'substract':
				total-= values;
				break;
				
		}
		
	}
	
	return total;
	
}
console.log(calculate('substract', 100,50,25)); //25
var source = [4,5,6];
var target = [1,2,3,...source,7,8,9];

TYPE FUNDAMENTALS

JAVASCRIPT TYPES

  • boolean
  • number
  • string
  • null / undefined
  • object (functions, arrays, ...)

FUNCTION PARAMETER TYPES

function totalLength (x: any[], y: string): number {

	var total = x-length + y.length;
	return total;
	
}

UNION TYPES

function totalLength (x: (string | any[]), y: (string | any[])): number {

	var total = x-length + y.length;
	
	x.slice(0);
	
	if (x instanceof Array) {
	
		x.push('abc');
		
	} 
	
	if (x instanceof String) {
	
		x.substr(1);
		
	}
	
	return total;
	
}

FUNCTION OVERLOADS

You can define the function to accept either two string parameters or two array parameters by overloadingthe function using the next syntax:

function totalLength (x: string, y: string): number
function totalLength (x: any[], y: any[]): number
function totalLength (x: (string | any[]), y: (string | any[])): number {
	...	
}

CUSTOM TYPES

DEFINING CUSTOM TYPES WITH INTERFACES

interfaces Todo {

	name: string;
	completed?: boolean; // The question mark makes the property optional
	
}
interface ITodoService {

	add(todo: Todo): Todo;
	delete(todoId: number): void; // Used when a function doesn't return anything
	getAll(): Todo[]; // Returns an array of Todo objects
	getById(todoId: number): Todo;
	
}

var todo: Todo = {

	name: 'Pick up drycleaning'
	
};

DESCRIBE FUNCTIONS WITH INTERFACES

interface jQuery {

	(selector: string): HTMLElement;
	version: number;
	
}

Casting syntax (type assertions) <jQuery> forces typescript into treating the next function as an instance of jQuery interface no matter what type of data Typescript thinks the variable is.

var $ = <jQuery>function (selector) { 
	// Find DOM element
};
$.version = 1.12;

var element = $('#container');

EXTENDING INTERFACE DEFINITIONS

For this you need to create a brand new interface that shares the same name as the one you want to extend.

interface jQueryElement {

	data(name: string): any;
	data(name:string, data: any): jQueryElement;
	
}
interface jQueryElement {

	todo(): Todo;
	todo(todo: Todo): jQueryElement;
	
}

DEFINING CONSTANT VALUES WITH ENUMS

Enums are a way to define a set of meaningful constant values.

interface Todo {

	name: string;
	state: TodoState;
	
}

enum TodoState {

	New = 1, // All of the following members are auto-incremented from this point on
	Active,
	Complete,
	Deleted
	
}

function delete (todo: Todo) {

	if (todo.state !== TodoState.Complete) {
	
		throw 'Can't delete incomplete task!';
		
	}
	
}

var todo: Todo = {

	name: 'Pick up drycleaning',
	state: TodoState.New
	
};

DEFINING ANONYMOUS TYPES

var todo: { name: string };

function totalLength (x: { length: number }, y: {length: number}): number {

	return x.length + y.length;
	
}

CLASSES

DEFINING A CLASS

TS:

class TodoService {

	constructor (private todos: Todo[]) {
	}
	
	getAll () {
	
		return this.todos;
		
	}
	
}

ES5:

var TodoService = (function () {

	function TodoService (todos) {
	
		this.todos = todos;
		
	}
	
	TodoService.prototype.getAll = function () {
	
		return this.todos;
		
	};
	
	return TodoService;
	
})();

APPLYING STATIC PROPERTIES

class TodoService {
	
	static lastId: number = 0;
	
	constructor (private todos: Todo[]) {
	}
	
	getAll () {
	
		return this.todos;
		
	}
	
}

ACCESSORS

interface Todo {

	name: string;
	state: TodoState;
	
}

enum TodoState {

	New = 1, // All of the following members are auto-incremented from this point on
	Active,
	Complete,
	Deleted
	
}

var todo: Todo = {

	name: 'Pick up drycleaning',
	get state () {

		return this._state;
		
	},
	set state(newState) {
        
		if (newState === TodoState.Complete) {

			var canBeCompleted = this.state == TodoState.Active
                		|| this.state == TodoState.Deleted;

			if (!canBeCompleted) {

				throw 'Todo must be Active or Deleted in order to be marked as Completed';

			}

		}

		this._state = newState;

	}
	
};

todo.state = TodoState.Complete;
todo.state;
class SmartTodo {

	_state: TodoState;
	name: string;
	
	get state () {

		return this._state;
		
	}
	
	set state(newState) {
        
		if (newState === TodoState.Complete) {

			var canBeCompleted = this.state == TodoState.Active
                		|| this.state == TodoState.Deleted;

			if (!canBeCompleted) {

				throw 'Todo must be Active or Deleted in order to be marked as Completed';

			}

		}

		this._state = newState;

	}
	
	constructor (name: string) {
	
		this.name = name;
		
	}
}

var todo = new SmartTodo('Pick up drycleaning');
todo.state = TodoState.Complete;

INHERITING BEHAVIOR FROM A BASE CLASS

class TodoStateChanger {

	constructor (private newState: TodoState) {}
	
	canChangeState (todo: Todo): boolean {
	
		return !!todo;
		
	}
	
	changeState (todo: Todo): Todo {
	
		if (this.canChangeState(todo)) {
		
			todo.state = this.newState;
			
		}
		
		return todo;
		
	}
	
}

class CompleteTodoStateChanger extends TodoStateChanger{
	
	constructor () {
		
		super(TodoState.Complete); // Base class constructor.
		
	}
	
	canChangeState (todo: Todo): boolean {
		
		// Super in this context is the base class object.
		return super.canChangeState(todo) && (
			todo.state == TodoState.Active
			|| todo.state == TodoState.Deleted
		); 
		
	}
	
}

IMPLEMENTING AN ABSTRACT CLASS

Abstract classes are only defined in order to act as base classes and are not meant to be instantiated.

abstract class TodoStateChanger {

	constructor (private newState: TodoState) {}
	
	// Every derived class must implement it's own canChangeState method
	
	abstract canChangeState (todo: Todo): boolean; 
	
	changeState (todo: Todo): Todo {
	
		if (this.canChangeState(todo)) {
		
			todo.state = this.newState;
			
		}
		
		return todo;
		
	}
	
}

MODIFIERS

  • public default modifier
  • private When a member is marked private, it cannot be accessed from outside of its containing class.
  • protected The protected modifier acts much like the private modifier with the exception that members declared protected can also be accessed by instances of deriving classes.

IMPLEMENTING INTERFACES

The primary reason interfaces exist in static languages is to attatch them to classes to make sure that they behave the way you expect them to. The way to do it is by using the implements keyword.

interface Todo {

	id: number;
	name: string;
	state: TodoState;
	
}

interface ITodoService {

	add (todo: Todo): Todo;
	getAll(): Todo[];
	
}

class TodoService implements ITodoService {

	private static lastId: number = 0;
	
	constructor (private todos: Todo[]) {}
	
	get nextId () {
		
		return TodoService.lastId += 1;
		
	}
	
	add (todo: Todo) {
	
		var newId = this.nextId;
		
	} 
	
	getAll () {
	
		return this.todos;
		
	}
	
}

GENERICS

Generics are a way to create components that can work over a variety of types rather than a single one.

function clone <T> (value: T): T {

	let serialized = JSON.stringify(value);
	return JSON.parse(serialized);
	
}

clone('Hello!'); // function clone<string>(value: string): string
clone(123); // function clone<string>(value: number): number

CREATING GENERIC CLASSES

var array: number[] = [1, 2, 3];
var array2: Array<number> = [1, 2 , 3];

class KeyValuePair <TKey, TValue> {

	constructor (
	
		public key: TKey,
		public value: TValue
		
	) {}
	
}

let pair1 = new KeyValuePair <number, string> (1, 'First');
let pair2 = new KeyValuePair <string, Date> ('Second', new Date(Date.now()));
let pair3 = new KeyValuePair <number, string> (3, 'Third');

class KeyValuePairPrinter <T, U> {

	constructor (private pairs: KeyValuePair<T, U>[]) {}
	
	print () {
	
		for (let p of this.pairs) {
		
			console.log(`${p.key}: ${p.value}`);
			
		}
		
	}
	
}

var printer = new KeyValuePairPrinter([pair1, pair3]);
printer.print();

APPLYING GENERIC CONSTRAINTS

function totalLength <T extends { length: number }> (x: T, y: T) {

	var total = x.length + y.length;
	return total;
	
}

var length = totalLength('Jess', 'Roger');
interface IHaveALength {

	length: number;
	
}

function totalLength <T extends IHaveALength> (x: T, y: T) {

	var total = x.length + y.length;
	return total;
	
}

var length = totalLength('Jess', 'Roger');

MODULES

DECORATORS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment