- 追加された行はこのように表示されます。
- 削除された行は
このように表示されます。
[移動しました|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