typescript Angular最终版本的Angular 2测试片段。代码库https://developers.livechatinc.com/blog/category/programming/angular-2/

Angular最终版本的Angular 2测试片段。代码库https://developers.livechatinc.com/blog/category/programming/angular-2/

app-3-router.spec.ts
// App
import { Component } from '@angular/core';
import { Routes } from '@angular/router';

@Component({
  selector: 'app',
  template: `<router-outlet></router-outlet>`
})
class AppComponent {}

// App tests
import { async, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';

import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';

TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());

describe('AppComponent', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [AppComponent],
      imports: [RouterTestingModule]
    });
  });

  it('should be able to test', async(() => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.whenStable().then(() => {
      expect(true).toBe(true);
    });
  }));

});
app-3-http.spec.ts
// App
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

@Injectable()
export class TestService {
  constructor(private http: Http) {}

  getUsers() {
    return this.http.get('http://foo.bar');
  }
}


// App tests
import { inject, TestBed } from '@angular/core/testing';

import { BaseRequestOptions, Response, ResponseOptions } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';

import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';

TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());

describe('Http', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        TestService,
        BaseRequestOptions,
        MockBackend,
        {
          provide: Http,
          useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
            return new Http(backend, defaultOptions);
          },
          deps: [MockBackend, BaseRequestOptions],
        },
      ],
    });
  });

  beforeEach(inject([MockBackend], (backend: MockBackend) => {
    const baseResponse = new Response(new ResponseOptions({ body: 'got response' }));
    backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));
  }));

  it('should return response when subscribed to getUsers', inject([TestService], (testService: TestService) => {
    testService.getUsers().subscribe((res: Response) => {
      expect(res.text()).toBe('got response');
    });
  }));

})
app-2-services.spec.ts
// App
class TestService {
  public name: string = 'Injected Service';
}


// App tests
import { inject, TestBed } from '@angular/core/testing';

import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';

TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());


describe('TestService', () => {

  beforeEach(() => {
    this.testService = new TestService();
  });

  it('should have name property set', () => {
    expect(this.testService.name).toBe('Injected Service');
  });

});


describe('TestService Injected', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [TestService],
    });
  });

  it('should have name property set', inject([TestService], (testService: TestService) => {
    expect(testService.name).toBe('Injected Service');
  }));

});


class MockTestService {
  public mockName: string = 'Mocked Service';
}

describe('TestService Mocked', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [{ provide: TestService, useClass: MockTestService }],
    });
  });

  it('should have name property set', inject([TestService], (testService: TestService) => {
    expect(testService.mockName).toBe('Mocked Service');
  }));

});


class MockTestServiceInherited extends TestService {
  public sayHello(): string {
    return this.name;
  }
}

describe('TestService Mocked Inherited', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [{ provide: TestService, useClass: MockTestServiceInherited }],
    });
  });

  it('should say hello with name', inject([TestService], (testService: TestService) => {
    expect(testService.sayHello()).toBe('Injected Service');
  }));

});
app-2-components.spec.ts
// App
import { Component, Input } from '@angular/core';

@Component({
  selector: 'list',
  template: '<span *ngFor="let user of users">{{ user }}</span>',
})
export class ListComponent {
  @Input() public users: Array<string> = [];
}


// App tests
import { async, inject, TestBed } from '@angular/core/testing';

import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';

TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());


describe('ListComponent', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ListComponent]
    });

    this.fixture = TestBed.createComponent(ListComponent);
  });

  it('should render list', async(() => {
    const element = this.fixture.nativeElement;
    this.fixture.componentInstance.users = ['John'];
    this.fixture.detectChanges();
    expect(element.querySelectorAll('span').length).toBe(1);
  }));

});



// App DI
class UserService {
  public users: Array<string> = ['John'];
}

@Component({
  selector: 'list',
  template: '<span *ngFor="let user of users">{{ user }}</span>',
})
class ListComponentBootstrapDI {
  private users: Array<string> = [];

  constructor(userService: UserService) {
    this.users = userService.users;
  }
}


class MockUserService {
  public users: Array<string> = ['John', 'Steve'];
}

describe('ListComponent DI', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ListComponentBootstrapDI],
      providers: [{ provide: UserService, useClass: MockUserService }],
    });

    this.fixture = TestBed.createComponent(ListComponentBootstrapDI);
  });

  it('should render list', async(() => {
    const element = this.fixture.nativeElement;
    this.fixture.detectChanges();
    expect(element.querySelectorAll('span').length).toBe(2);
  }));

});


// App DI for Component
@Component({
  selector: 'list',
  template: '<span *ngFor="let user of users">{{ user }}</span>',
  providers: [UserService],
})
class ListComponentComponentDI {
  private users: Array<string> = [];

  constructor(userService: UserService) {
    this.users = userService.users;
  }
}

// App DI for Component tests
describe('ListComponent DI Component', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ListComponentBootstrapDI],
    });

    this.fixture = TestBed
      .overrideComponent(ListComponentBootstrapDI, {
        set: {
          providers: [{ provide: UserService, useClass: MockUserService }],
        },
      })
      .createComponent(ListComponentBootstrapDI);
  });

  it('should render list', async(() => {
    const element = this.fixture.nativeElement;
    this.fixture.detectChanges();
    expect(element.querySelectorAll('span').length).toBe(2);
  }));

});
app-1.spec.ts
// App
import { Component } from '@angular/core';

@Component({
  selector: 'app',
  template: '<span>{{ sayHello() }}</span>',
})
export class App {
  public name: string = 'John';

  sayHello(): string {
    return `Hello ${this.name}`;
  }
}


// App tests

describe('App', () => {

  beforeEach(() => {
    this.app = new App();
  });

  it('should have name property', () => {
    expect(this.app.name).toBe('John');
  });

  it('should say hello with name property', () => {
    expect(this.app.sayHello()).toBe('Hello John');
  });

});

typescript 旧的遗忘物

旧的遗忘物

PrimitiveObjects.ts
//typescript version of built in objects

interface Obj {
    type:string;
    repr():any;
    display():any;
    increment():void;
    decrement():void;
    concat(other:any):void;
    index(key:any):any;
    setitem(key:any, other:any):void;
    append(other:any):void;
    pop():any;
    remove(key:any):void;
    count(other:any):any;
    contains(other:any):any;
    length():any;
    insert(key:any, other:any):void;
    add(other:any):any;
    subtract(other:any):any;
    multiply(other:any):any;
    divide(other:any):any;
    remainder(other:any):any;
    power(other:any):any;
    addassign(other:any):void;
    subassign(other:any):void;
    multiplyassign(other:any):void;
    divideassign(other:any):void;
    remainderassign(other:any):void;

}

class NumberObj implements Obj {
    public value:number;
    public type:string;

    constructor(value:any) {
        this.type = "number";
        this.value = value;
    }
    public repr() {
        return this.value;
    }
    public display() {
        return this.value.toString();
    }
    public increment() {
        this.value += 1;
    }
    public decrement() {
        this.value -= 1;
    }
    public concat(other:NumberObj) {
        this.value = parseInt(this.value.toString() + other.value.toString());
    }
    public index(other:NumberObj) {
        if(other.value < 0) {
            return new NumberObj(-1);
        }
        else if(other.value < this.value) {
            return new NumberObj(1)
        }
        else {
            return new NumberObj(0);
        }
    }
    public insert(key:NumberObj, other:NumberObj) {
        this.value += other.value;
    }
    public add(other:NumberObj) {
        return new NumberObj(this.value + other.value);
    }
    public subtract(other:NumberObj) {
        return new NumberObj(this.value - other.value);
    }
    public multiply(other:NumberObj) {
        return new NumberObj(this.value * other.value);
    }
    public divide(other:NumberObj) {
        if(other.value === 0) {
            return new NumberObj(this.value);
        }
        else {
            return new NumberObj(this.value / other.value);
        }
    }
    public remainder(other:NumberObj) {
        return new NumberObj(this.value % other.value);
    }
    public power(other:NumberObj) {
        return new NumberObj(Math.pow(this.value, other.value));
    }
    public addassign(other:NumberObj) {
        this.value += other.value;
    }
    public subassign(other:NumberObj) {
        this.value -= other.value;
    }
    public multiplyassign(other:NumberObj) {
        this.value *= other.value;
    }
    public divideassign(other:NumberObj) {
        if(other.value === 0) {
            this.value += 0;
        }
        else {
            this.value /= other.value;
        }
    }
    public remainderassign(other:NumberObj) {
        this.value %= other.value;
    }
    public setitem(key:NumberObj, other:NumberObj) {
        this.value += other.value - 1;
    }
    public append(other:NumberObj) {
        this.value += other.value;
    }
    public pop() {
        this.value -= 1;
        if(this.value >= 0) return new NumberObj(1);
        else return new NumberObj(-1);
    }
    public remove(key:NumberObj) {
        this.value -= 1;
    }
    public count(other:NumberObj) {
        if (other.value === 0) {
            return new NumberObj(0);
        }
        else {
            return new NumberObj(Math.floor(this.value / other.value));
        }
    }
    public length() {
        return new NumberObj(this.value.toString().length);
    }
    //returns a boolean, must be updated to return a bool object
    public contains(other:NumberObj) {
        return other.value < this.value;
    }

}

class StringObj implements Obj {
    public value:string[];
    public type:string;

    constructor(value:any) {
        this.type = "string";
        this.value = value.split("");
    }
    public repr() {
        return this.value.join("");
    }
    public display() {
        return '"' + this.value.join("") + '"';
    }
    public length() {
        return new NumberObj(this.value.length);
    }
    public concat(other:StringObj) {
        this.value = this.value.concat(other.value);
    }
    //adds a space to end of string
    public increment() {
        this.value = this.value.concat([" "]);
    }
    public decrement() {
        this.value.pop();
    }
    public index(key:NumberObj) {
        return new StringObj(this.value[key.value]);
    }
    public insert(key:NumberObj, other:StringObj) {
        if (key.value >= 0 && key.value < this.value.length) {
            for(var i=0;i<other.value.length;i++) {
                this.value.splice(key.value, 0, other.value[i]);
            }
        }
        else {
            //if index is out of bounds, will set at zero position
            for(var i=0;i<other.value.length;i++) {
                this.value.splice(0, 0, other.value[i]);
            }
        }
    }
    //destructive version of insert method for strings.
    public setitem(key:NumberObj, other:StringObj) {
        if (key.value >= 0 && key.value < this.value.length) {
            this.value.splice(key.value, 1);
            for(var i=0;i<other.value.length;i++) {
                this.value.splice(key.value, 0, other.value[i]);
            }
        }
        else {
            this.value.splice(0, 1);
            //if index is out of bounds, will set at zero position
            for(var i=0;i<other.value.length;i++) {
                this.value.splice(0, 0, other.value[i]);
            }
        }
    }
    public add(other:StringObj) {
        return new StringObj(this.value.join("") + other.value.join(""));
    }
    public append(other:StringObj) {
        this.value = this.value.concat(other.value);
    }
    public pop() {
        return new StringObj(this.value[this.value.length]);
    }
    public remove(key:StringObj) {
        this.value = this.value.join("").replace(key.repr(), "").split("");
    }
    public count(other:StringObj) {
        var count = 0;
        var tempstring = this.value.join("")
        while(tempstring.search(other.repr()) !== -1) {
            count += 1;
            tempstring = tempstring.replace(other.repr(), "");
        }
        return new NumberObj(count);
    }
    public contains(other:StringObj) {
        return new BoolObj(this.repr().search(other.repr()) !== -1);
    }
    public subtract(other:StringObj) {
        return new StringObj(this.value.join("").replace(other.repr(), ""));
    }
    public multiply(other:StringObj) {
        var count = other.value.length;
        var newstr = new StringObj(this.repr());
        for(var i=0;i<count;i++) {
            newstr.append(other);
        }
        return newstr;
    }
    //produces a repeat string object of the sum of both strings lengths attributes
    public power(other:StringObj) {
        var newlength = this.value.length + other.value.length;
        var newstr = new StringObj("");
        for(var i=0;i<newlength;i++) {
            newstr.append(this);
            newstr.append(other);
        }
        return newstr;
    }
    //returns a string split by the other string as the delimeter
    public divide(other:StringObj) {
        return new StringObj(this.repr().split(other.repr()));
    }
    //remove all oeprator for strings
    public remainder(other:StringObj) {
        var patt = new RegExp(other.repr(), "g");
        return new StringObj(this.value.join("").replace(patt, ""));
    }
    public addassign(other:StringObj) {
        this.append(other);
    }
    public subassign(other:StringObj) {
        this.value = this.value.join("").replace(other.repr(), "").split("");
    }
    public multiplyassign(other:StringObj) {
        var count = other.value.length;
        for(var i=0;i<count;i++) {
            this.append(other);
        }
    }
    public divideassign(other:StringObj) {
        this.value = this.repr().split(other.repr());
    }
    public remainderassign(other:StringObj) {
        var patt = new RegExp(other.repr(), "g");
        this.value = this.value.join("").replace(patt, "").split("");
    }
}
//range object
class RangeObj {

    public type:string;
    public start:NumberObj;
    public end:NumberObj;

    constructor(start:NumberObj, end:NumberObj) {
        this.type = "range";
        this.start = start;
        this.end = end;
    }
    //returns an object containing the start and end points of the range
    public repr() {
        return {end:this.end.repr(), start:this.start.repr()};
    }
    public display() {
        return this.start.display() + "<-->" + this.end.display();
    }
    public increment() {
        this.start.value += 1;
        this.end.value += 1;
    }
    public decrement() {
        this.start.value -= 1;
        this.end.value -=1;
    }

    public concat(other:RangeObj) {

    }
    public index(other:NumberObj) {

    }

}

class ListObj implements Obj {

    public value:any[];
    public type:string;

    constructor() {
        this.value = [];
        this.type = "list";
    }
    public repr() {
        return this.value;
    }
    public display() {
        return JSON.stringify(this.value);
    }
    public increment() {
        this.value.push(new NothingObj());
    }
    public decrement() {
        this.value.pop();
    }
    public concat(other:ListObj) {
        this.value = this.value.concat(other.value);
    }
    public index(key:NumberObj) {
        var ind = key.value % this.value.length;
        return this.value[ind];
    }
    public setitem(key:NumberObj, other:any) {
        if(key.value >= 0 && key.value < this.value.length) {
            this.value[key.value] = other;
        }
        else if(key.value < 0) {
            this.value[0] = other;
        }
        else {
            this.value[this.value.length-1] = other;
        }
    }
    public append(other:any) {
        this.value.push(other);
    }
    public pop() {
        return this.value.pop();
    }
    public remove(key:NumberObj) {
        var ind = key.value % this.value.length-1;
        this.value.splice(ind, 1);
    }
    public count(other:any) {
        var total = 0;
        for(var i=0;i<this.value.length;i++) {
            if (this.value[i] === other) {
                total += 1;
            }
        }
        return new NumberObj(total);
    }
    //linear search
    public contains(other:any) {
        var contain = false;
        for(var i=0;i<this.value.length;i++) {
            if(this.value[i] === other) {
                return new BoolObj(true);
            }
        }
        return new BoolObj(contain);
    }
    public length() {
        return new NumberObj(this.value.length);
    }
    public insert(key:NumberObj, other:any) {
        var ind = key.value % this.value.length;
        this.value.splice(ind, 0, other);
    }
    public add(other:ListObj) {
        var newlist = new ListObj();
        newlist.value = this.value.concat(other.value);
        return newlist;
    }
    //subtracts all items in one list, from the other list
    public subtract(other:ListObj) {
        var newlist = new ListObj();
        for(var i=0;i<this.value.length;i++) {
            for(var j=0;j<other.value.length;j++) {
                if(this.value[i] === other.value[j]) {
                    newlist.append(other.value[i]);
                }
            }
        }
        return newlist;
    }
    public multiply(other:ListObj) {
        var newlist = new ListObj();
        for(var i=0;i<other.value.length;i++) newlist.value = this.value.concat(other.value);
        return newlist;
    }
    //future implementation, needs revising
    public divide(other:any) {
        return this;
    }
    //future implementation
    public remainder(other:ListObj) {
        return this;
    }
    public power(other:ListObj) {
        return this;
    }
    public addassign(other:ListObj) {
        this.append(other);
    }
    public subassign(other:ListObj) {
        this.value = this.subtract(other).value;
    }
    public multiplyassign(other:ListObj) {
        this.value = this.multiply(other).value;
    }
    public divideassign(other:any) {
        this.value = this.divide(other).value;
    }
    public remainderassign(other:ListObj) {
        this.value = this.remainder(other).value;
    }
}

class SetObj implements Obj {

    public type:string;
    public value:Object;
    constructor() {
        this.type = "set";
        this.value = {};
    }
    public repr() {
        return this.value;
    }
    public display() {
        return JSON.stringify(this.value);
    }
    public increment() {

    }
    public decrement() {

    }
    public concat(other:SetObj) {
        for(var key in other.value) {
            if(!(key in this.value)) {
                this.value[key] = true;
            }
        }
    }
    //same as contains, returns bool object
    public index(key:any) {
        var boolresult = JSON.stringify(key) in this.value;
        return new BoolObj(boolresult);
    }
    public setitem(key:any, other:any) {
        this.value[JSON.stringify(key)] = true;
    }
    public append(other:any) {
        var key = JSON.stringify(other);
        if(!(key in this.value)) {
            this.value[key] = true;
        }
    }
    //returns a random object from the set
    public pop() {
        for(var key in this.value) {
            return JSON.parse(key);
        }
    }
    public remove(other:any) {
        var stringed = JSON.stringify(other);
        delete this.value[stringed];
    }
    public count(other:any) {
        if(JSON.stringify(other) in this.value) {
            return new NumberObj(1);
        }
        else {
            return new NumberObj(0);
        }
    }
    public contains(other:any) {
        var boolresult = JSON.stringify(other) in this.value;
        return new BoolObj(boolresult);
    }
    public length() {
        var amount = 0;
        for(var key in this.value) amount += 1;
        return new NumberObj(amount);
    }
    public insert(key:any, other:any) {
        this.append(other);
    }
    //returns union of both sets in a new set
    public add(other:SetObj) {
        var newset = new SetObj();
        for(var key in this.value) newset.append(key);
        for(var key in other.value) newset.append(key);
        return newset;
    }
    public subtract(other:SetObj) {

    }

}

class MapObj {

}

class BoolObj {
    public state:Boolean;
    public type:String;

    constructor(state:Boolean) {
        this.state = state;
        this.type = "Bool";
    }
    public repr() {
        return this.state;
    }
}
//implements the nothing type
class NothingObj {
    public type:String;

    constructor() {
        this.type = "nothing"
    }

    public repr() {
        return this;
    }

    public display() {
        return this.type;
    }
}

class RiftObj {

}

typescript Color.ts

Color.ts
interface Color{}
class Red implements Color{}
class Green implements Color{}
class Blue implements Color{}
class Rgb implements Color {
  constructor(public r: number,public g: number,public b: number) {
  }
}

function to_hex(n: number): string {
	return n.toString(16).toUpperCase();
}

function to_s(c: Color): string {
	switch(Object.getPrototypeOf(c)) {
		case Red.prototype:
			return "#FF0000";
		case Green.prototype:
			return "#00FF00";
		case Blue.prototype:
			return "#0000FF";
		case Rgb.prototype: {
			return "#" + to_hex((<Rgb>c).r) + to_hex((<Rgb>c).g) + to_hex((<Rgb>c).b);	
		}
	}
}

let c = new Rgb(255,255,255);
alert(to_s(c));

typescript 角度2 Ng对象。特别是一个火力列表。

角度2 Ng对象。特别是一个火力列表。

messages.pipe.ts
import {Pipe, PipeTransform} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import * as R from 'ramda';
@Pipe({
  name: 'messages'
})
/**
 * Take an object that is key value id message and convert it to a array of ChatMessage throwing the id in the message.
 */
export class MessagesPipe implements PipeTransform {
  transform(input: any, args: any[] = []): any[] {
    if (input) {
      /**
       * Compose a function by converting the object to a pairs array of [[key, value], ...]
       * Then map over the array and take the head of each pair and throw it into the tail (value) as the id.
       * Flatten the two dimensional array and return.
       */
      return R.compose(R.flatten, R.map((x) => {
        return R.assoc('id', R.head(x), R.last(x));
      }), R.toPairs)(input);
    }
  }
}

typescript 可观测量RxJS

可观测量RxJS

Observables
export class AppComponent {
  title = 'app';

  observable$;

  ngOnInit() {
    // create an observable
    this.observable$ = Observable.create((observer) => {
      observer.next(1);
      observer.next(2);
      observer.next(3);
      observer.complete();
    });
    this.observable$.subscribe(
      value => console.log(value),
      err => {},
      () => console.log('this is the end')
    );    
  }

  ngOnDestroy() {
    // unsubscribe an observable, otherwise it'll keep on listening even if the component is destroyed
    this.observable$.unsubscribe();
  }
}


/*

A stream is a sequence of ongoing events ordered in time. It can emit three different things:
a value (of some type), an error, or a "completed" signal. 

We capture these emitted events only asynchronously, by defining a function that will execute when a value 
is emitted, another function when an error is emitted, and another function when 'completed' is emitted. 

Sometimes these last two can be omitted and you can just focus on defining the function for values. 
The "listening" to the stream is called subscribing. The functions we are defining are observers.
The stream is the subject (or "observable") being observed. This is precisely the Observer Design Pattern.

--a---b-c---d---X---|->

a, b, c, d are emitted values
X is an error
| is the 'completed' signal
---> is the timeline

In common Reactive libraries, each stream has many functions attached to it, such as  map ,  filter ,  scan , etc. 
When you call one of these functions, such as  clickStream.map(f) , it returns a new stream based on the 
click stream. It does not modify the original click stream in any way. This is a property called immutability, 
and it goes together with Reactive streams just like pancakes are good with syrup. 
That allows us to chain functions like  clickStream.map(f).scan(g) 

Book on rxjs: http://xgrommx.github.io/rx-book/content/guidelines/introduction/index.html

*/

typescript TypeScript基础知识

TypeScript基础知识

TypeScript basics.ts
/*
  Types:
  Many people do not realize it, but JavaScript does in fact have types, they're just "Duck
  Typed", which roughly means that the developer does not have to think about them.
  
  JavaScript's types also exist in TypeScript:
   boolean: (true/false)
   number: integers, floats, Infinity , and NaN
   string: characters, and strings of characters
   []: Arrays of other types, like number[] or boolean[]
   {}: Object literal
   undefined: not set
   
  TypeScript also adds
   enum: enumerations like { Red, Blue, Green }
   any: use any type
   void: nothing
*/

// Primitive type example:
  let isDone: boolean = false;
  let height: number = 6;
  let name: string = "bob";
  let list: number[] = [1, 2, 3];
  let list: Array<number> = [1, 2, 3];
  enum Color {Red, Green, Blue};
  let c: Color = Color.Green;
  let notSure: any = 4;
  notSure = "maybe a string instead";
  notSure = false;
  
  function showMessage(data: string): void {
    alert(data);
  }
  showMessage('hello');

// optional parameters using ?
  function logMessage(message: string, isDebug?: boolean)
  {
    if (isDebug) {
    console.log('Debug: ' + message);
    } else {
    console.log(message);
    }
  }

/*Typescript classes
  TypeScript also treats classes as their own type
*/

  class Foo { foo: number; }
  class Bar { bar: string; }
  class Baz {
    constructor(foo: Foo, bar: Bar) { }
  }

/*Interfaces
  Sometimes classes are "more" than a developer wants. Classes end up creating code, in the
  form of transpiled ES2015 classes, or transpiled ES5 constructor functions.
  
  Interfaces are abstract descriptions of things. Interfaces can be used to represent any non-primitive
  JavaScript object. Interfaces   are literally "abstract" in the sense that they produce no code,
  ES2015, or ES5. Interfaces exist only to describe types to tsc.
*/

// Here is an example of an interface describing an Object literal:
  interface Action {
    name: string;
  }
  
  let a: Action = {
    name: 'clean kitchen today'
  }

/* Shapes 
  Underneath TypeScript is JavaScript, and underneath JavaScript is typically a JIT (just in
  time compiler). Given JavaScript's underlying semantics, types are typically reasoned about
  by "shapes". These underlying "shapes" work like TypeScript's interfaces, and are in fact
  how TypeScript compares custom types like classes, and interfaces.
*/

// Consider an expansion of the previous example:
  interface Action {
    name: string;
  }
  let a: Action = {
    name: 'clean kitchen today'
  }
  class NotAnAction {
    name: string;
    constructor() {
      this.name = 'Constructor function (class)';
    }
  }
  a = new NotAnAction(); // valid TypeScript!

/*
  Despite the fact that Action, and NotAnAction have different identifiers, tsc lets us
  assign an instance of NotAnAction to 'a' which has a type of Action . This is because
  TypeScript only really cares that Objects have the same "shape". In other words if two
  objects have the same attributes, with the same typings, those two objects are considered to
  be of the same type.
*/

typescript 使用tsc

使用tsc

Working With tsc.ts
/*So far tsc has been used to compile a single file. Typically developers have a lot more
than one file to compile. Thankfully tsc can handle multiple files as arguments.
Imagine two ultra simple files/modules: a.ts, b.ts */

//a.ts
export const A = (a) => console.log(a);

//b.ts
export const B = (b) => console.log(b);

// the following will give error
$ tsc ./a.ts ./b.ts

/*
TypeScript supports a number of different module schemes.
For the moment commonjs is desirable. This will produce modules that are compatible with
node.js's module system.
*/

$ tsc -m commonjs ./a.ts ./b.ts
/*
tsc should produce no output. In many command line traditions, no output is actually a
mark of success. Listing the directory contents will confirm that our TypeScript files did in
fact compile. 

Telling the tsc command what to compile becomes tedious, and labour intensive even on
small projects. Fortunately TypeScript has a means of simplifying this. tsconfig.json files
let developers write down all the compiler settings they want. When tsc is run, it looks for
tsconfig.json files, and uses their rules to compile JavaScript.

For Angular 2 projects there are a number of specific settings that need to be configured in a
project's tsconfig.json
*/
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noImplicitAny": false,
"removeComments": false,
"sourceMap": true
},
"exclude": [
"node_modules",
"dist/"
]
}

// target
//The compilation target. Typescript supports targeting different platforms depending on your
//needs. In our case, we're targeting modern browsers which support ES5.

// module
// The target module resolution interface. We're integrating TypeScript through webpack which
//supports different interfaces. We've decided to use node's module resolution interface,
//commonjs .

/* TypeScript with Webpack 
We won't be running tsc manually, however. Instead, Webpack's ts-loader will do the
transpilation during the build:

This loader calls tsc for us, and it will use our tsconfig.json .
*/

// webpack.config.js
//...
loaders: [
{ test: /\.ts$/, loader: 'ts', exclude: /node_modules/ },
//...
]

/* Typings 
Astute readers might be wondering what happens when TypeScript programmers need to
interface with JavaScript modules that have no type information. TypeScript recognizes files
labelled *.d.ts as definition files. These files are meant to use TypeScript to describe
interfaces presented by JavaScript libraries.
There are communities of people dedicated to creating typings for JavaScript projects. There
is also a utility called typings ( npm install --save-dev typings ) that can be used to
manage third party typings from a variety of sources.

*/

/*Linting

Many editors support the concept of "linting". Linting is basically grammar check for
computer programs. Linting can be done in a programmer's editor, and/or through
automation.
For TypeScript there is a package called tslint , ( npm install --save-dev ts-lint ) which
can be plugged into many editors. tslint can also be configured with a tslint.json file.
Webpack can also run tslint before it even attempts to run tsc . This is done by
installing tslint-loader ( npm install --save-dev tslint-loader ) which plugs into webpack
like so:
// ...
module: {
preLoaders: [
{ test: /\.ts$/, loader: 'tslint' }
],
loaders: [
{ test: /\.ts$/, loader: 'ts', exclude: /node_modules/ },
// ...
]
// ...
}

*/

typescript 打字稿介绍

打字稿介绍

Typescript Intro
/* 
  ES2015 is the upcoming version of JavaScript. TypeScript is a superset of ES2015, which means all
  ES2015 features are part of TypeScript, but not all TypeScript features are part of ES2015.
  Consequently, TypeScript must be transpiled into ES5 to run in most browsers.
  One of TypeScript's primary features is the addition of type information, hence the name.
  This type information can help make JavaScript programs more predictable, and easier to
  reason about.
  Types let programmers write more explicit "contracts", in other words, things like function
  signatures are more explicit. This is true for both humans, and the TypeScript compiler.
*/

// Without TypeScript
function add(a, b) {
return a + b;
}
add(1, 3); // 4
add(1, '3'); // '13'

// With TypeScript
function add(a: number, b: number) {
 return a + b;
}
add(1, 3); // 4
// compiler error before JS is even produced
add(1, '3'); // '13'


// We can install the TypeScript transpiler using npm:
$ npm install -g typescript

// We can then use tsc to manually compile a TypeScript source file into ES5:
$ tsc test.ts
$ node test.js

// Our earlier ES2015 class won't compile now. TypeScript is more demanding than ES2015 and it
// expects instance properties to be declared:

class Pizza {
  toppings: string[];
  constructor(toppings: string[]) {
    this.toppings = toppings;
  }
}

/*
  Note that now that we've declared toppings to be an array of strings, TypeScript will
  enforce this. If we try to assign a number to it, we will get an error at compilation time.
  If you want to have a property that can be set to a value of any type, however, you can still
  do this: just declare its type to be "any":
*/
class Pizza {
  toppings: any;
}

typescript 打字稿+角度1的启动片段

打字稿+角度1的启动片段

service.ts
/// <reference path="../../include.ts" />
"use strict";
module STEN.Services {


    export interface IService {
        
        Method();
    }

    export class Service implements IService {
        
        static $inject: Array<string> = ["$http"];
        constructor(public $http: ng.IHttpService) {

        }
        public Method() {
           }
    }
}
include.ts
// main
/// <reference path="./app/app-init.ts" />


// typings
/// <reference path="../../typings/angularjs/angular.d.ts" />


// services
/// <reference path="./services/Service.ts" />
controller.ts
/// <reference path="../../include.ts" />

module APP.Controllers {
    'use strict';
   
    import Services = STEN.Services.Account;
  
    export class Ctrl {
      
        static $inject: Array<string> = ["Service"];
        constructor(public service: Services.IService) {
          
        }

        public Method() {
         
        }


}

    var app = APP.Init.getApp([...commonDependancies]);
    app
        .service("Service", Services.Service)
        .controller('Ctrl', Ctrl)
}
app-init.ts
/// <reference path="../include.ts" />
var commonDependancies = ["..."];
var apiPath = "http://localhost:8080";

module APP.Init {
    export var getApp: (dependancies: Array<string>) => ng.IModule = (dependancies) => {
        var app = angular.module("APP", dependancies);
        
        return app;
    }
}

typescript Bootstrap混合Angular 1和2

Bootstrap混合Angular 1和2

boot.ts
import {UpgradeAdapter} from 'angular2/upgrade';
import {Ng2Book} from './ng2/ng2.component';

var adapter = new UpgradeAdapter();

app.directive('ng2Book', adapter.downgradeNg2Component(Ng2Book));

adapter.bootstrap(document.body, ['AdminApp']);