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すれば、正常に実行できるようになります。