[TypeScript]interface

// Shape インターフェースの定義
interface Shape {
  color: string;
  getArea(): number; // メソッドの型のみ定義
  describe(): void;
}

// Circle クラス
class Circle implements Shape {
  constructor(public color: string, private radius: number) {}

  getArea(): number {
    return Math.PI * this.radius ** 2;
  }

  describe(): void {
    console.log(`This is a ${this.color} circle.`);
  }
}

// Rectangle クラス
class Rectangle implements Shape {
  constructor(public color: string, private width: number, private height: number) {}

  getArea(): number {
    return this.width * this.height;
  }

  describe(): void {
    console.log(`This is a ${this.color} rectangle.`);
  }
}

// インスタンス作成
const circle = new Circle("red", 10);
console.log(circle.getArea()); // 314.159...
circle.describe(); // This is a red circle.

const rectangle = new Rectangle("blue", 5, 8);
console.log(rectangle.getArea()); // 40
rectangle.describe(); // This is a blue rectangle.

特徴 interface abstract class
インスタンス化 不可 不可
プロパティ・メソッドの型定義 型のみ 型+実装
コンストラクタ なし あり
複数の継承 可能(多重継承OK) 不可能(単一継承のみ)

 

複数のinterfaceをimplementsするクラス

// 移動可能なオブジェクトのインターフェース
interface Movable {
  speed: number;
  move(): void;
}

// 描画可能なオブジェクトのインターフェース
interface Drawable {
  color: string;
  draw(): void;
}

// CarクラスがMovableとDrawableを両方実装
class Car implements Movable, Drawable {
  constructor(public speed: number, public color: string) {}

  move(): void {
    console.log(`The car is moving at ${this.speed} km/h.`);
  }

  draw(): void {
    console.log(`Drawing a ${this.color} car.`);
  }
}

// インスタンス作成
const myCar = new Car(100, "red");

myCar.move();  // The car is moving at 100 km/h.
myCar.draw();  // Drawing a red car.

 
オブジェクトに使用

interface User {
  name: string;
  age: number;
}

const user: User = {
  name: "Taro",
  age: 25,
};

console.log(user.name); // "Taro"
console.log(user.age);  // 25

interface User {
  name: string;
  age?: number; // ageは省略可能
}

const user1: User = { name: "Taro" }; // OK
const user2: User = { name: "Jiro", age: 30 }; // OK

 
関数に使用

interface Greeting {
  (name: string): string;
}

const sayHello: Greeting = (name) => `Hello, ${name}!`;

console.log(sayHello("John")); // "Hello, John!"

 
配列に使用

interface NumberArray {
  [index: number]: number;
}

const numbers: NumberArray = [1, 2, 3, 4];

console.log(numbers[0]); // 1

 
キャストする

interface Car {
  brand: string;
  model: string;
}

const myCar = {
  brand: "Toyota",
  model: "Corolla",
  year: 2023, // 追加のプロパティ
} as Car; // `year`は無視される

console.log(myCar.brand); // "Toyota"
console.log(myCar.model); // "Corolla"

[TypeScript]抽象クラス

abstract class Shape {
    // コンストラクタで共通のプロパティを定義
    constructor(protected color: string) {}
  
    // 具体的なメソッド(サブクラスでそのまま使える)
    describe(): void {
      console.log(`This is a ${this.color} shape.`);
    }
  
    // 抽象メソッド(サブクラスで実装必須)
    abstract getArea(): number;
  }
  
  class Circle extends Shape {
    constructor(color: string, private radius: number) {
      super(color);
    }
  
    // 必須の抽象メソッドを実装
    getArea(): number {
      return Math.PI * this.radius ** 2;
    }
  }
  
  class Rectangle extends Shape {
    constructor(color: string, private width: number, private height: number) {
      super(color);
    }
  
    getArea(): number {
      return this.width * this.height;
    }
  }
  
  // インスタンス作成
  const circle = new Circle("red", 10);
  console.log(circle.getArea()); // 314.159...
  circle.describe(); // This is a red shape.
  
  const rectangle = new Rectangle("blue", 5, 8);
  console.log(rectangle.getArea()); // 40
  rectangle.describe(); // This is a blue shape.
  

[TypeScript]クラス

class Parent{
    static PI:number = 3.1415926535;
    protected static readonly gratio = 1.618;
    public name:string;
    public prop:number = 10;
    protected gender:string;
    private _abc:number;
    constructor(name:string){
        this.name = name;
    }
    get abc():number{
        return this._abc;
    }
    set abc(value:number){
        this._abc = value;
    }
    showMessage(message:string){
        console.log(`Hello ${this.name}!. ${message}`);
    }
}

class Child extends Parent{
    public prop:number = 22;//プロパティのオーバーライド
    public age :number;
    private prop2:string;
    constructor(name:string,age:number){//constructorのオーバーライド
        super(name);
        this.age = age;
    }
    showMessage(message:string){//メソッドのオーバーライド
        console.log(`Hello ${this.name}!. ${message} age:${this.age}`);
    }
}

 
通常

class Article{
    public name:string;
    protected prop:number = 10;
    private prop2:number = 10;
    constructor(name:string,prop:number,prop2:number){
        this.name = name;
        this.prop = prop;
        this.prop2 = prop2;
    }
}

 
省略記法

class Article{
    constructor(
       public name:string,
       protected prop:number,
       private prop2:number
    ){}
}

[JavaScript]CartChecker.js

/**
 * カートチェッカー
 */
class CartChecker{
    /**
     * Creates an instance of CartChecker.
     *
     * @constructor
     */
    constructor() {}
    /**
     * updateCart
     *
     * @param {*} sendData
     * @returns {Promise}
     */
    updateCart(sendData){
        return new Promise((resolve,reject) => {
            const url = window._routes && window._routes.cart_update_url ? window._routes.cart_update_url+'.js' : '/cart/update.js';
            const options = {
                method  : "POST",
                headers : {
                    "Content-Type" : "application/json"
                },
                body    : sendData
            };
            fetch(url,options)
                .then((response)=>{
                    if (!response.ok) {
                        throw new Error();
                    }
                    return response.json();
                })
                .then((json)=>{
                    resolve(json);
                })
                .catch((error)=>{
                    reject(error);
                });
        });
    }
    /**
     * changeCart
     *
     * @param {*} sendData
     * @returns {Promise}
     */
    changeCart(sendData){
        return new Promise((resolve,reject) => {
            const url = window._routes && window._routes.cart_change_url ? window._routes.cart_change_url+'.js' : '/cart/change.js';
            const options = {
                method  : "POST",
                headers : {
                    "Content-Type" : "application/json"
                },
                body    : sendData
            };
            fetch(url,options)
                .then((response)=>{
                    if (!response.ok) {
                        throw new Error();
                    }
                    return response.json();
                })
                .then((json)=>{
                    resolve(json);
                })
                .catch((error)=>{
                    reject(error);
                });
        });
    }
    /**
     * cart.jsからのレスポンスを返す
     *
     * @returns {Promise}
     */
    getCart(){
        return new Promise((resolve,reject) => {
            const url = window._routes && window._routes.cart_url ? window._routes.cart_url+'.js' : '/cart.js';
            fetch(url)
                .then((response)=>{
                    if (!response.ok) {
                        throw new Error();
                    }
                    return response.json();
                })
                .then((json)=>{
                    resolve(json);
                })
                .catch((error)=>{
                    reject(error);
                });
        });
    }
    /**
     * getLineItemPropertiesByLineItemKey
     *
     * @param {String} lineItemKey
     * @returns {Promise}
     */
    getLineItemPropertiesByLineItemKey(lineItemKey){
        return new Promise((resolve,reject) => {
            const url = window._routes && window._routes.cart_url ? window._routes.cart_url+'.js' : '/cart.js';
            fetch(url)
                .then((response)=>{
                    if (!response.ok) {
                        throw new Error();
                    }
                    return response.json();
                })
                .then((json)=>{
                    let i,item;
                    for(i=0;i<json.items.length;i++){
                        item = json.items[i];
                        if(item.key === lineItemKey){
                            resolve(item.properties);        
                            break;
                        }
                    }
                    resolve(null);
                })
                .catch((error)=>{
                    reject(error);
                });
        });
    }
}

[TypeScript]インターセクション型

type Product = {
    title:string;
    price:number;
};

type User = {
    name:string;
};

type Order = Product & User;

const firstOrder :Order = {
    title : "走れメロス",
    price : 512,
    name  : "John Smith",
};

console.log(firstOrder);
{ title: '走れメロス', price: 512, name: 'John Smith' }

[TypeScript]配列とタプル

string型配列

let titles: string[];

 
tuple型

let order:[number,string] = [64,"John Smith"];

 
NG

order = [128,"Jeff Mike",1024];

 
NG

console.log(order[2]);

 
ラベル付き

type Order = [id:number,title:string,price?:number,...memo:any[]];

priceはオプショナル
…memoには複数の要素が入る

NG

let firstOrder:Order  = [1];

 
OK

let secondOrder:Order = [1,"あいうえお"];

 
OK

let thirdOrder:Order  = [1,"あいうえお",1024,true,512,"かきくけこ"];

 

type Order = [id:number,title:string,price?:number,...memo:any[]];
let secondOrder:Order = [1,"あいうえお"];
let thirdOrder:Order  = [1,"あいうえお",1024,true,512,"かきくけこ"];
console.log(secondOrder);
console.log(thirdOrder);
console.log(thirdOrder[0]);
console.log(thirdOrder[1]);
console.log(thirdOrder[2]);

上記を実行すると下記が出力される

[ 1, 'あいうえお' ]
[ 1, 'あいうえお', 1024, true, 512, 'かきくけこ' ]
1
あいうえお
1024

[TypeScript]readonlyプロパティ

type Order = {
    readonly id : number;
    title : string;
    price : number;
};

 
変数

const firstOrder : Order = {
    id : 2,
    title : "あいうえお",
    price : 512,
};

 
変更OK

firstOrder.title = "かきくけこ";

 
変更NG

firstOrder.id = 3;

[TypeScript]型エイリアス

型エイリアス

type DataType = number | string;
type EventName = "click" | "hover" | "mousedown";

※型エイリアスはブロックスコープ
 
使う時

let firstDataType : DataType = 123;

 
型エイリアスのユニオン

type Team = ATeam | BTeam;
type ATeam = "john" | "jeff" | "joe";
type BTeam = "mike" | "migera" | "mika";
let partner:Team = "mike";

 
オブジェクトの時
通常

let article : {
    id    : number;
    title : string;
    body  : string;
} = {
    id    : 875,
    title : "あいうえお",
    body  : "かきくけこ",
};

 
型エイリアス

type Article = {
    id    : number;
    title : string;
    body  : string;
};
const article : Article = {
    id    : 875,
    title : "あいうえお",
    body  : "かきくけこ",
};

 
ネストパターン1

type Order = {
    id : number;
    title : string;
    price : number;
    product : {
        title : string;
        price : number;
    };
};

 
ネストパターン2

type Product = {
    title : string;
    price : number;
};
type Order = {
    id : number;
    title : string;
    price : number;
    product : Product;
};