トップ 一覧 ping 検索 ヘルプ RSS ログイン

TypeScriptの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
[移動しました|https://www.typea.info/tips_/index.php/TypeScript]
!!![このページは移動しました|https://www.typea.info/tips_/index.php/TypeScript]
*https://www.typea.info/tips_/index.php/TypeScript

!!!TypeScript
[Node.js][Angular][Google Cloud Platform]
{{amazon B0733113NK}}

*https://www.typescriptlang.org/docs/home.html

!!準備
!install
 > npm install -g typescirpt

!init
::tsconfig.json の生成
 > tsc --init
!Visual Studio Code タスク
F1 - task run - build tsconfig.json

!Playground
*動作確認や、どのようなJavascriptに変換されるか確認
*https://www.typescriptlang.org/play/
{{ref_image ts_playground.jpg}}
!!!変数・型
!!変数・定数
,変数宣言,ブロックスコープ,同じスコープでの重複宣言,備考
,var,認識しない,認める
,let,認識する,認めない
,const,認識する,認めない,再代入不可
!!型
,型,説明
,number,数値
,string,文字列
,boolean,真偽
,symbol,シンボル
,any,任意
,オブジェクト
!!文字列リテラル
!`バッククオートで囲む
*改行もそのまま
*${...} ...に変数、式を埋め込み
 class Program {
     static main() {
         let name: string = "Hiroto Yagi";
         let age = 46;   // 型推論
         // age = "Hello"; // 数値型に文字列代入エラー
         let msg = null; // 初期値未指定、null指定など、any型と類推され型チェックは働かない
         msg = 100;      // noImplicitAny:true とすると、暗黙的 anyは許容しない
         msg = "Hello";
     
         // テンプレート文字列
         console.log(`
         ${msg} 
         my name is ${name} 
         age ${age}
         ${new Date()}`);
     }
 }
 
 Program.main();
::結果
 > node ./src/app.js
 
        Hello
        my name is Hiroto Yagi
        age 46
        toda Tue Nov 07 2017 18:59:23 GMT+0900 (東京 (標準時))
!!型アサーション
*キャスト
 function show(message: string) {
     console.log(`${message}`);
 }
 class TypeAssartion {
     static main() {
         // show(10);    // ERROR
         show(<any>10);  // OK
         show(10 as any); // as もOK
     }
 }
!!コレクション/インターフェース
 interface StringMap {
     [index:string]:string;
 }
 class Collection {
     static main() {
         // 配列
         let languages: string[] = ['java','C#','python'];
         console.log(languages);
 
         // 連想配列
         let fwMap: {[key:string]:string} = {
             'java':'Spring',
             'C#':'Asp.net',
             'python':'Django'
         };
         console.log(fwMap);
 
         // インデクスシグネチャはinterfaceとして事前定義可
         let fwMap2: StringMap = {
             'java':'Spring',
             'C#':'Asp.net',
             'python':'Django'
         };
         console.log(fwMap2);
     }
 }
!!列挙
 enum Animal {
     DOG,
     CAT,
     MOUSE,
     ELEPHANT
 }
 enum Fruit {
     APPLE = "A",
     ORANGE = "O",
     PAINAPPLE = "P"
 }
 class EnumSample {
     static main() {
         let mypet: Animal = Animal.DOG;
         // デフォルトで0からの数値が割り当てられる
         console.log(mypet);
         console.log(Animal[mypet]);
         
         let myfavarit: Fruit = Fruit.PAINAPPLE;
         // 列挙子に値を割り当てることも可能
         console.log(myfavarit);
     }
 }
::結果
 0
 DOG
 P
!!タプル
 let tpl: [string, number, boolean] = ['Yagi', 46, true];
 console.log(`name:${tpl[0]} age:${tpl[1]} marriged:${tpl[2]}`);
!!共用型
 let data: string | boolean;
 data = 'foo';// OK
 data = true; // OK
 // data = 1; // NG
 
 let datas: (boolean | number)[] = [true, false, 1, 0];
!!型エイリアス
 // 主にタプル、共用型に別名を付与。インターフェースでできる場合に使用しないほうがよい
 type ProfileTuple = [string, number, boolean];
 let me = ['yagi', 46, true];        
 console.log(`name:${me[0]} age:${me[1]} marriged:${me[2]}`);
!!文字列リテラル
 type Season = 'spring' | 'summer' | 'autumn' | 'winter';
 class StringLiteralType {
     printSeason(s: Season) {
         console.log(s);
     }
     static main() {
         let me = new StringLiteralType();
         me.printSeason('summer');  // OK
         // me.printSeason('hoge'); // NG
     }
 }
!!!関数
*function命令
*関数リテラル
*アロー関数
!!関数、関数リテラル、アロー関数
 function squire(x: number, y: number) :number {
     return x * y;
 }
 class FunctionSample{
     static main() {
         // 関数の使用
         console.log(squire(8,8));
 
         // 関数リテラル(型推論)
         let m3 = function(x :number, y: number, z: number): number {
             return x * y * z;
         } ;
         console.log(m3(8,8,8));
 
         // 関数リテラル(型明示)
         let m2: (x: number, y: number) => number = function(x: number, y: number) {
             return x * y;
         };
         console.log(m2(9,9));
         
         // アロー関数(ラムダ式)
         // this は宣言された場所によって変わる
         let m22 = (x: number, y: number): number =>  x * y;
         console.log(m22(5,5));
     }
 }
!!引数の省略、デフォルト引数、可変長引数
 class FunctionApplySample {
     static main(){
         // TypeScriptでは宣言された引数はすべて必須
         // 引数を省略したい場合、仮引数の名前の後ろに ? を付与
         let greet = function(message?: string){
             message = (message === undefined)?"hello":message;
             console.log(message);
         }
         greet();
         greet("good evening");
     
         // 関数のデフォルト値を設定するには、仮引数の後に=デフォルト値
         // デフォルト値には、式も利用できる
         // 明示的に undefined を渡した場合もデフォルト値が利用される
         let greet2 = function(message: string=`hello ${new Date()}`) {
             console.log(message);
         }
         greet2();
         greet2("good night");
         greet2(undefined);
 
         // 可変長引数
         // 仮引数の前に、... とすることで可変長引数となる
         let sum = function(...nums: number[]):number {
             let ttl: number = 0;
             nums.forEach((value,index,array) => ttl += value);
             return ttl;
         }
         console.log(sum(1,2,3,4,5));
     }
 }
!!関数のオーバーロード
 function showMessage(value: number): void;
 function showMessage(value: boolean): void;
 function showMessage(value: any): void {
     let message: string | undefined;
     if (typeof value === 'number') {
         message = `${value} is number.`;
     }
     if (typeof value === 'boolean') {
         message = `${value} is boolean`;
     }
     console.log(message);
 }
 class FunctionApplySample2 {
     static main(){
         console.log("*** 関数応用2 ***");
         // 1.シグネチャのみの関数を用意
         // 2.具体的な実装を直後に定義
         // 3.実装の中で、typeof/instanceof を用いて型を判定し処理を記述
         showMessage(123);
         showMessage(false);
         showMessage("Hello" as any);
     }
 }
!!!オブジェクト指向
!!クラス定義
 class Person {
     // メンバー
     name: string; // デフォルト public
     private _age: number; 
 
     // 静的メンバー
     public static CHEAT_AGES: number = 2;
     
     // コンストラクター
     constructor(name: string, age: number){
         this.name = name;
         this._age = age;
     }
 
     // 以下のコンストラクターでメンバーの宣言と代入を省略できる
     // アクセス修飾子必須
     // constructor(public name: string, private _age: number) {
     // }
 
     // アクセッサー
     get age(): number {
         return this._age - Person.CHEAT_AGES;
     }
     set age(value: number) {
         this._age = value;
     }
 
     // メソッド
     printProfile(){
         console.log(`name=${this.name},age=${this.age}`);
     }
 }
 console.log(Person.CHEAT_AGES);
 let me = new Person('Yagi', 46);
 //console.log(me.age); // NG
 me.printProfile();
 me.age = 50;
 me.printProfile();
::結果
 2
 name=Yagi,age=44
 name=Yagi,age=48
!!名前空間
*namespace ブロックで定義
*exportで外側からアクセス可能なことを明示
*完全修飾名で呼び出す
 namespace NameA {
     export class Foo {
         name() {
             console.log("NameA.Foo");
         }
     }
     export function bar(){
         console.log("NameA.bar()");
     }
 }
 let foo = new NameA.Foo();
 foo.name();
 NameA.bar();
!名前空間のネスト
 namespace NameB {
     export namespace NameC {
         export function bar(){
             console.log("NameB.NameC.bar()");
         }
     }
 }
 NameB.NameC.bar(); 
!!継承
 class Guiter {
     constructor(public maker: string, public type: string){}
     print() {
         console.log(`${this.type} by ${this.maker}`);
     }
 }
 class Lespaul extends Guiter {
     constructor(){
         super("Gibson","Lespaul");
     }
 }
 (new Lespaul()).print();
!!抽象クラス
 // 抽象クラス
 abstract class Viecle {
     // 抽象メソッド
     abstract getEngineDisplacement(): number;
     printDisplacement() {
         console.log(`${this.getEngineDisplacement()}`);
     }
 }
 class Premacy extends Viecle {
     // 抽象メソッドのオーバーライド
     getEngineDisplacement(): number {
         return 2000;
     }
     // メソッドオーバーライド
     printDisplacement() {
         console.log("******");
         super.printDisplacement();
         console.log("******");
     }
 }
 (new Premacy()).printDisplacement();
!!インターフェース
 interface Color {
     // メソッドはすべて抽象メソッド
     // abstract 指定は不要
     getRGB(): string;
 }
 class Red implements Color {
     getRGB(): string {
         return "#FF0000";
     }
 }
 console.log((new Red()).getRGB());

!!構造的部分型(Structual subtyping)
 class Hoge {
     constructor(public name: string, public age: number){}
 }
 class Spam {
     constructor(public name: string, public age: number){}
 }
 // 継承による明示的な互換性(Nominal subtyping)がなくても構造が一致していれば代入可能
 let h: Hoge = new Spam("spam",10);
 console.log(h);

!!型注釈としてのインターフェース
*インターフェースを型注釈として利用できる
 interface Shape {
     // プロパティシグネチャ
     name: string;
     // メソッドシグネチャ
     draw():void;
 }
 let c : Shape = {
     name:'circle',
     draw() {
         console.log(`${this.name}:○`);
     } 
 };
 c.draw();

!オブジェクトリテラル
*インターフェースを定義するまでもないが、型情報は明示しておきたい場合
 let t : { name: string, sides: number} = {name: 'triangle', sides: 3};
!!型としてのthis
 class StringBuilder {
     constructor(protected _value: string){
     }
     toString(): string {
         return this._value;
     }
     wrap(value: string) :string{
         return `${value}`;
     }
     // 自分自身を返すことで、メソッドチェーンのような記述が可能となる
     // 派生クラスなど、呼び出し元のクラスに応じ型が変化する
     append(value: string): this {
         this._value = this._value + this.wrap(value);
         return this;
     }
 }
 let buf = new StringBuilder('a');
 buf.append('b').append('c').append('d');
 console.log(buf.toString());
 
 class CsvBuilder extends StringBuilder {
     constructor(protected _value: string){
         super(_value);
     }
     wrap(value: string) {
         return `,${value}`;
     }
 }
 let csv = new CsvBuilder('a');
 csv.append('b').append('c').append('d');
 console.log(csv.toString());
::出力
 abcd
 a,b,c,d
!!ジェネリック
 let numary: Array<number> = [1,2,3,5,8];
!ジェネリック型の定義 
*StringBuilder型は、上記で定義参照
 class XmlBuilder extends StringBuilder {
     constructor(protected _value: string){
         super(_value);
     }
     wrap(value: string) {
         return `<value>${value}</value>`;
     }
     toString(): string {
         return `<values>${this._value}</values>`;
     }
 }
 
 // 型引数に制約を付与する場合、extends を使用する。
 // 使用しなければ、あらゆる型を渡すことができる
 class Report<T extends StringBuilder> {
     builder: T;
     getBuilder(): T {
         return this.builder;
     }
     addLine(line: string) {
         this.getBuilder().append(line);
     }
     report() {
         console.log(this.getBuilder().toString());
     }
 }
 let rep = new Report<XmlBuilder>();
 // ジェネリック型に具体的なインスタンスを紐づけ
 rep.builder = new XmlBuilder('');
 rep.addLine("this is lesson.");
 rep.addLine("of TypeScript.")
 rep.report();
::出力例
 <values><value>this is lesson.</value><value>of TypeScript.</value></values> 

!ジェネリックメソッド
 function reverse<T>(data: T[]): T[] {
     let ary: T[] = new Array();
 
     let j=0;
     for(let i=data.length-1; i>=0; i--) {
         ary[j++] = data[i];
     }
     return ary;
 }
 console.log(reverse<number>([1,2,3,4]));
 console.log(reverse<string>(["a","b","c","d"]));
::出力例
 [ 4, 3, 2, 1 ]
 [ 'd', 'c', 'b', 'a' ]

!!サンプル
{{ref app.ts}}

!!!Tips
!!TypeDoc
*https://qiita.com/Mic-U/items/961ce4e0c2a1def1dbd3
*https://qiita.com/ConquestArrow/items/eb4a0dfb13497be4d6a3
!インストール
 > npm install typedoc -g
!作成
 > typedoc --out ./docs/ ./src/ --module commonjs