Skip to content

Instantly share code, notes, and snippets.

@jchadwick
Last active August 29, 2015 14:19
Show Gist options
  • Save jchadwick/925256e3f72a5fbec304 to your computer and use it in GitHub Desktop.
Save jchadwick/925256e3f72a5fbec304 to your computer and use it in GitHub Desktop.
Presentation Snippets: TypeScript
interface IAnimal {
name: string;
sayName(): void;
}
class Animal implements IAnimal {
private _name: string = '[Animal]';
get name(): string {
return this._name;
}
set name(name: string) {
this._name = name;
}
constructor(name: string) {
this.name = name;
}
sayName() {
console.log(
`Rectangle area is ${this.name}`
);
}
}
class Dog extends Animal {
bark() {
console.log('WOOF!');
}
}
var animal: IAnimal = new Dog('Fido');
animal.sayName();
(<Dog>animal).bark();
class LocalStorageTodoService extends TodoServiceBase implements ITodoService {
static $inject = ['$q', 'localStorage'];
private static CacheKey = 'todo-items';
private todos: Todo[] = [];
constructor(private $q: ng.IQService, private localStorage) {
super();
var cached = localStorage.getItem(LocalStorageTodoService.CacheKey);
this.todos = JSON.parse(cached || '[]');
}
clearCompleted() {
// Delegate functions for filtering
var ids = this.todos.filter((x) => x.state == TodoState.Completed)
.reduce((prev, x) => prev.concat(x.id), []);
ids.forEach(this.remove.bind(this));
return this.$q.when(ids);
}
getAll() {
return this.$q.when(this.todos);
}
create(todo) {
// "Overload" that converts a string to an object
if (typeof (todo) === 'string') {
todo = { name: todo };
}
todo.id = this._nextId();
todo.state = TodoState.Active;
this.todos.push(todo);
this._save(this.todos);
return this.$q.when(todo);
}
remove(id) {
var todo = this._find(id),
index = this.todos.indexOf(todo);
this.todos.splice(index, 1);
this._save(this.todos);
return this.$q.when(id);
}
update(todo) {
var existing = this._find(todo.id);
if (existing) {
existing.state = todo.state;
existing.name = todo.name;
this._save(this.todos);
}
return this.$q.when(todo);
}
/* Private Methods */
private _find(id) {
var filtered = this.todos.filter((x) => x.id == id);
return filtered.length ? filtered[0] : null;
}
private _nextId() {
var ids = this.todos.map((todo) => {
return todo.id;
});
var maxId = ids.reduce((highest, curr) => Math.max(highest, curr), 1);
return maxId + 1;
}
private _save(todos) {
this.localStorage.setItem(LocalStorageTodoService.CacheKey, JSON.stringify(this.todos));
}
protected _setComplete(id, isComplete) {
var state = isComplete ? TodoState.Completed : TodoState.Active,
todo = this._find(id);
if (todo) {
todo.state = state;
this._save(this.todos);
}
return this.$q.when(todo);
}
}
class ProxyTodoService {
static $inject = ['$http', 'serviceUrl'];
private static unwrap(resp) {
return resp && resp.data || {};
}
constructor(private $http, private serviceUrl) {
this.complete = this._generateSetCompleteDelegateFor(true);
this.uncomplete = this._generateSetCompleteDelegateFor(false);
}
clearCompleted() {
var url = [this.serviceUrl, 'clear'].join('/');
return this.$http.post(url).then(ProxyTodoService.unwrap);
}
create(todo) {
return this.$http.post(this.serviceUrl, todo).then(ProxyTodoService.unwrap);
}
getAll() {
return this.$http.get(this.serviceUrl).then(ProxyTodoService.unwrap);
}
remove(id) {
var url = [this.serviceUrl, id].join('/');
return this.$http.delete(url).then(ProxyTodoService.unwrap);
}
update(todo) {
var url = [this.serviceUrl, todo.id].join('/');
return this.$http.put(url, todo).then(ProxyTodoService.unwrap);
}
complete(todoId) { throw 'Not implemented!'; }
uncomplete(todoId) { throw 'Not implemented!'; }
/* Private Methods */
private _setComplete(todoId: number, isComplete: boolean) {
var state = isComplete ? 'complete' : 'uncomplete',
url = [this.serviceUrl, todoId, state].join('/');
return this.$http.post(url).then(ProxyTodoService.unwrap);
}
private _generateSetCompleteDelegateFor(isComplete: boolean) {
return (todoId: number) => {
return this._setComplete(todoId, isComplete);
}
}
}
class ProxyTodoService implements ITodoService {
static $inject = ['$http', 'serviceUrl'];
private static unwrap<T>(resp: ng.IHttpPromiseCallbackArg<T>) {
return resp && resp.data || true;
}
constructor(private $http: ng.IHttpService, private serviceUrl: string) {
this.complete = this._generateSetCompleteDelegateFor(true);
this.uncomplete = this._generateSetCompleteDelegateFor(false);
}
clearCompleted() {
var url = [this.serviceUrl, 'clear'].join('/');
return this.$http.post<number[]>(url, null).then(ProxyTodoService.unwrap);
}
create(todo: Todo) {
return this.$http.post<Todo>(this.serviceUrl, todo).then(ProxyTodoService.unwrap);
}
getAll() {
return this.$http.get<Todo[]>(this.serviceUrl).then(ProxyTodoService.unwrap);
}
remove(id: number) {
var url = [this.serviceUrl, id].join('/');
return this.$http.delete<boolean>(url).then(ProxyTodoService.unwrap);
}
update(todo: Todo) {
var url = [this.serviceUrl, todo.id].join('/');
return this.$http.put<Todo>(url, todo).then(ProxyTodoService.unwrap);
}
complete(todoId: number) { throw 'Not implemented!'; }
uncomplete(todoId: number) { throw 'Not implemented!'; }
/* Private Methods */
private _setComplete(todoId: number, isComplete: boolean) {
var state = isComplete ? 'complete' : 'uncomplete',
url = [this.serviceUrl, todoId, state].join('/');
return this.$http.post(url).then(ProxyTodoService.unwrap);
}
private _generateSetCompleteDelegateFor(isComplete: boolean) {
return (todoId: number) => {
return this._setComplete(todoId, isComplete);
}
}
}
class ProxyTodoService extends TodoServiceBase implements ITodoService {
static $inject = ['$http', 'serviceUrl'];
private static unwrap<T>(resp: ng.IHttpPromiseCallbackArg<T>) {
return resp && resp.data || true;
}
constructor(private $http: ng.IHttpService, private serviceUrl: string) {
super();
}
clearCompleted() {
var url = [this.serviceUrl, 'clear'].join('/');
return this.$http.post<number[]>(url, null).then(ProxyTodoService.unwrap);
}
create(todo: Todo) {
return this.$http.post<Todo>(this.serviceUrl, todo).then(ProxyTodoService.unwrap);
}
getAll() {
return this.$http.get<Todo[]>(this.serviceUrl).then(ProxyTodoService.unwrap);
}
remove(id: number) {
var url = [this.serviceUrl, id].join('/');
return this.$http.delete<boolean>(url).then(ProxyTodoService.unwrap);
}
update(todo: Todo) {
var url = [this.serviceUrl, todo.id].join('/');
return this.$http.put<Todo>(url, todo).then(ProxyTodoService.unwrap);
}
protected _setComplete(todoId: number, isComplete: boolean) {
var state = isComplete ? 'complete' : 'uncomplete',
url = [this.serviceUrl, todoId, state].join('/');
return this.$http.post(url).then(ProxyTodoService.unwrap);
}
}
class ProxyTodoService implements ITodoService {
static $inject = ['$http', 'serviceUrl'];
private static unwrap(resp) {
return resp && resp.data || true;
}
constructor(private $http, private serviceUrl: string) {
this.complete = this._setCompleteDelegateFor(true);
this.uncomplete = this._setCompleteDelegateFor(false);
}
clearCompleted() {
var url = [this.serviceUrl, 'clear'].join('/');
return this.$http.post(url).then(ProxyTodoService.unwrap);
}
create(todo: Todo) {
return this.$http.post(this.serviceUrl, todo).then(ProxyTodoService.unwrap);
}
getAll() {
return this.$http.get(this.serviceUrl).then(ProxyTodoService.unwrap);
}
remove(id: number) {
var url = [this.serviceUrl, id].join('/');
return this.$http.delete(url).then(ProxyTodoService.unwrap);
}
update(todo: Todo) {
var url = [this.serviceUrl, todo.id].join('/');
return this.$http.put(url, todo).then(ProxyTodoService.unwrap);
}
complete(todoId: number) { throw 'Not implemented!'; }
uncomplete(todoId: number) { throw 'Not implemented!'; }
/* Private Methods */
private _setComplete(todoId: number, isComplete: boolean) {
var state = isComplete ? 'complete' : 'uncomplete',
url = [this.serviceUrl, todoId, state].join('/');
return this.$http.post(url).then(ProxyTodoService.unwrap);
}
private _setCompleteDelegateFor(isComplete: boolean) {
return (todoId: number) => {
return this._setComplete(todoId, isComplete);
}
}
}
class TodoList {
static $inject = ['$log', 'TodoService'];
todos = [];
constructor(private _$log, private _todoService) {
this._loadTodos();
}
addTodo(todo) {
// "Overload" that converts a string to an object
if (typeof todo === 'string')
todo = { name: todo };
return this._todoService.create(todo).then((added) => {
this.todos.push(added);
return added;
});
}
clearCompleted() {
return this._todoService.clearCompleted().then((deleted) => {
var deletedTodos = this._findTodos(deleted);
this._removeTodos(deletedTodos);
});
}
getStateName(todoState) {
if (todoState) {
var name = TodoState[todoState];
if (name)
return name.toLowerCase();
}
this._$log.warn('Unknown todo state: ', todoState);
return '**INVALID**';
}
nextState(todo) {
switch (todo.state) {
case TodoState.Active:
this._completeTodo(todo);
break;
case TodoState.Completed:
this._uncompletedTodo(todo);
break;
default:
this._$log.warn('Unknown todo state: ', todo.state);
break;
}
}
// Ignore this - for demo purposes only...
resetDemo() {
this.todos.forEach((todo) => {
this._deleteTodo(todo);
});
this.addTodo('Dryclean cape').then(() => {
this.addTodo({ name: 'Clean cave' }).then((todo) => {
this._completeTodo(todo);
}).then(() => {
this.addTodo('Save Gotham');
});
});
}
//#endregion
//#region "Private" methods
private _completeTodo(todo) {
return this._todoService.complete(todo.id).then(() => {
todo.state = TodoState.Completed;
});
}
private _deleteTodo(todo) {
this._todoService.remove(todo.id).then(() => {
this._removeTodo(todo);
});
}
private _findTodos(todoIds) {
todoIds = [].concat(todoIds);
return this.todos.filter((todo) => {
if (todo) {
for (var i = 0; i < todoIds.length; i++) {
if (todo.id == todoIds[i])
return true;
}
}
});
}
private _loadTodos() {
this._todoService.getAll().then((existing) => {
this.todos.splice.apply(this.todos, [0, existing.length].concat(existing))
});
}
private _uncompleteTodo(todo) {
return this._todoService.uncompleted(todo.id).then(() => {
todo.state = TodoState.Active;
});
}
private _removeTodos(toRemove) {
if (!toRemove) return;
// "Overload" the function by converting anything into an array
toRemove = [].concat(toRemove);
toRemove.forEach((todo) => {
var index = this.todos.indexOf(todo);
if (index >= 0) {
this.todos.splice(index, 1);
}
});
}
//#endregion
}
class TodoServiceBase {
constructor() {
this.complete = this._generateSetCompleteDelegateFor(true);
this.uncomplete = this._generateSetCompleteDelegateFor(false);
}
complete(todoId: number): ng.IPromise<boolean> { throw 'Not implemented!'; }
uncomplete(todoId: number): ng.IPromise<boolean> { throw 'Not implemented!'; }
protected _setComplete(todoId: number, isComplete: boolean): ng.IPromise<boolean> {
throw 'Not implemented!';
}
protected _generateSetCompleteDelegateFor(isComplete: boolean) {
return (todoId: number): ng.IPromise<boolean> => {
return this._setComplete(todoId, isComplete);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment