" />

スポンサーリンク

TypeScript

TypeScript入門2~クラス・インターフェース~

投稿日:

TypeScriptの関数

関数の書き方

// 名前付き関数
function createName(sei: string, mei: string) {
  return sei + mei;
}
console.log(createName("山田", "太郎")); // 山田太郎

// 関数式
let createName2 = function (sei: string, mei: string) {
  return sei + mei;
};
console.log(createName2("山田2", "太郎2")); // 山田2太郎2

// アロー関数
let createName3 = (sei: string, mei: string) => {
  return sei + mei;
};
console.log(createName3("山田3", "太郎3")); // 山田3太郎3

// アロー関数の省略記法
let createName4 = (sei: string, mei: string) => sei + mei;
console.log(createName4("山田4", "太郎4")); // 山田4太郎4

いずれも、パラメータにアノテーションをつけて型指定すれば良い。

関数の戻り値の型

function createName(sei: string, mei: string): string {
  return sei + mei;
}
console.log(createName("山田", "太郎")); // 山田太郎

戻り値の型を明示する場合は、パラメータの後にアノテーションで指定する。

デフォルトパラメータ

// デフォルトパラメータ
let createName5 = (sei: string, mei: string, middle: string = "") => {
  return sei + middle + mei;
};
console.log(createName5("山田5", "太郎5")); // 山田5太郎5
console.log(createName5("山田5", "太郎5", "ダニエル")); // 山田5ダニエル太郎5

パラメータに=値を付与することで、フォルト値を指定できる。
デフォルトパラメータは必須となるパラメータの後に書くこと。

TypeScriptのクラス

class Persion {
  private sei: string;
  private mei: string;

  constructor(sei: string, mei: string) {
    this.sei = sei;
    this.mei = mei;
  }

  public getName() {
    return this.sei + this.mei;
  }
}

const person = new Persion("山田", "花子");
console.log(person);
console.log(person.getName());

コンストラクタ...constructorに続けて記述する。

publicどこからでもアクセス可能。省略した場合はpublicとなる
protectedこのクラスのインスタンスと、子クラスのインスタンスからアクセス可能。
privateこのクラスのインスタンスからのみアクセス可能。
アクセス修飾子

TypeScriptのインターフェース

型に名前をつける方法としてインターフェースがある。
後述の型エイリアスとほぼ同じことができる。

// インターフェースの宣言
interface Human {
  name: string;
  age: number;
  talk(): void;
}

// インターフェースの実装クラス
class HumanImpl implements Human {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  talk(): void {
    console.log(this.name + "は" + this.age + "歳です.");
  }
}

// 使い方
const taro: Human = new HumanImpl("太郎", 35);
taro.talk(); // 太郎は35歳です.

型エイリアス(型リテラル)

インターフェース同様の機能に型エイリアスがあり、typeキーワードを用いて宣言する。

type Animal = {
  name: string;
  type: string;
  talk(): void;
};

class Cat implements Animal {
  name: string;
  type: string;

  constructor(name: string, type: string) {
    this.name = name;
    this.type = type;
  }

  talk(): void {
    console.log(this.name + "は" + this.type + "です.");
  }
}

const bob: Animal = new Cat("ボブ", "ネコ");
bob.talk();

型エイリアスもやはりimplementsすることによってインスタンス化が可能になるため、ほぼインターフェースと同じである。

インターフェースと型エイリアスの違いは3つあるが、小さいものである。
一般的に型エイリアスの方が汎用的にできているため、型エイリアスを使えば良い。

違い1.型エイリアスは型の式を割り当てることができる

interface Sample {} // type Sample = {} でも良い

type Hoge = Sample | string;

違い2.

違い3.型エイリアスは同じ識別子が重複できない

interface A {}
interface A {} // OK。上と下の内容がマージされる。

type B = {};
type B = {}; // エラー

TypeScriptのエラー処理

Javaにはthrow/throwsがあるが、TypeScriptにはthrowしかない。

function checkNum(num: number): boolean {
  if (num < 2) {
    return true;
  }
  throw new Error("エラー発生");
}

checkNum(3);

// 実行結果
    throw new Error("エラー発生");
    ^
Error: エラー発生
    at checkNum (/Users/noricgeographic/repositories/sandbox/ts1/dist/p168-error.js:6:11)
    at Object.<anonymous> (/Users/noricgeographic/repositories/sandbox/ts1/dist/p168-error.js:8:1)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
    at internal/main/run_main_module.js:17:47

エラーを任意の場所で発生させるには、上述のようにthrowキーワードに続いてErrorオブジェクトを指定する。

TypeSciptにはJavaのthrows節のように、呼び出し元に例外処理を強制する仕組みはないため、例外発生元が明示的に教えてあげるしかない。

モジュールのインポートとエクスポート

モジュールは1つのTypeScriptファイルである。

あるTypeScirptファイルAから、他のTypeScriptファイルBのクラス・関数・変数を使うには、
・ファイルBでクラス・関数・変数をexportする。
・ファイルAではクラスBのクラス・関数・変数をimportして使う。
という手順になります。

class Pokemon {
  private name: string;
  private hp: number;

  constructor(name: string, hp: number) {
    this.name = name;
    this.hp = hp;
  }

  public status(): void {
    console.log(this.name + "のHPは" + this.hp + "です。");
  }
}

const pikachu = new Pokemon("ピカ1", 100);
pikachu.status();

// 実行結果
ピカ1のHPは100です。
const pikachu2 = new Pokemon("ピカ2", 200);
pikachu2.status();

// 実行結果
pokemon-game.js:2
const pikachu2 = new Pokemon("ピカ1", 100);
                 ^

ReferenceError: Pokemon is not defined
    at Object.<anonymous> (/Users/noricgeographic/repositories/sandbox/ts1/dist/pokemon-game.js:2:18)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
    at internal/main/run_main_module.js:17:47

これで両ファイルを実行すると、
pokemon.tsは自身のモジュール内のクラスを参照しているため、正常に実行できます。

しかし、pokemon-game.tsのpikachu2は自身のモジュール外のクラスを参照しているため、エラーとなります。

export class Pokemon {
  private name: string;
  private hp: number;

  constructor(name: string, hp: number) {
    this.name = name;
    this.hp = hp;
  }

  public status(): void {
    console.log(this.name + "のHPは" + this.hp + "です。");
  }
}
import { Pokemon } from "./pokemon";

const pikachu2 = new Pokemon("ピカ2", 200);
pikachu2.status();

// 実行結果
ピカ2のHPは200です。

このように、pokemon.tsでPokemonクラスをexportし、
pokemon-game.tsでimportすれば、正常に実行できるようになります。

スポンサーリンク

-TypeScript

Copyright© ノリックジオグラフィック for Webエンジニア , 2022 All Rights Reserved Powered by AFFINGER5.