
TypeScript 入門
1. TypeScript
「TypeScript」は「JavaScript」を拡張したプログラミング言語です。
2. HelloWorld の作成
HelloWorld の作成の手順は、次のとおりです。
(1) 「Node.js」のインストール。
(2) プロジェクトフォルダの作成。
今回は、プロジェクトフォルダ名を「helloworld」としています。
$ mkdir helloworld
$ cd helloworld
(3) Node.jsプロジェクトのセットアップ。
$ npm init -y
設定ファイル「package.json」が生成されるので、次のように編集します。
・package.json
{
"name": "helloworld",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "tsc"
},
"keywords": [],
"author": "",
"license": "ISC",
}
設定項目は、次のとおりです。
・name : アプリ名
・version : アプリのバージョン
・description : アプリの説明
・main : メインスクリプト
・scripts : パッケージのコマンド設定
・keywords : キーワード
・author : 著者
・license : ライセンス
(4) TypeScriptプロジェクトのインストール。
$ npm install typescript --save-dev
(5) TypeScriptプロジェクトのセットアップ。
$ npx tsc --init
設定ファイル「tsconfig.json」が生成されるので、次のように編集します。
・tsconfig.json
{
"compilerOptions": {
"target": "es2016",
"lib": ["dom", "es2016"],
"module": "CommonJS",
"moduleResolution": "node",
"resolveJsonModule": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
}
}
設定項目は、次のとおりです。
・target : モジュールのJavaScriptのバージョン
・lib : どのようなライブラリ型定義を含めるか
・module : モジュールの形式
・moduleResolution : モジュールの解決方法
・resolveJsonModule : .jsonのインポート
・esModuleInterop : CommonJSのインポートのサポート
・forceConsistentCasingInFileNames : インポート時の大文字・小文字チェック
・strict : 厳密な型チェック
・skipLibCheck : .d.tsの型チェックのスキップ
(6) HelloWorldの作成。
次のコードを作成します。
・index.ts
let str: string = "Hello World!";
console.log(str);
(7) HelloWorldのビルド。
「index.js」が出力されます。
$ npm run build
(4) HelloWorldの実行。
$ node index.js
Hello World!
3. 変数と定数
3-1. 変数と定数
変数は「let」、定数は「const」で定義します。再代入が必要ない場合は「const」にします。
// 変数
let letValue = 1;
letValue = 2; // OK
// 定数
const constValue = 1;
// constValue = 2; // エラー
3-2. プリミティブ型
主なプリミティブ型は、次のとおりです。
const numberValue: number = 1; // 数値型
const stringValue: string = "ABC"; // 文字列型
const booleanValue: boolean = true; // boolean型
3-3. null と undefined
「null」はプロパティが空、「undefined」はプロパティが未定義を表します。
const nullValue: null = null; // null
const undefinedValue: undefined = undefined; // undefined
3-4. any と unknown
「any」と「unknown」はどの型でも代入できる型です。「any」は型付き変数に代入できますが、「unknown」は型付き変数に代入できません。
let anyValue: any = 1; // any
anyValue = "ABC"; // どの型でも代入可
let stringValue: string = anyValue; // OK
let unknownValue: unknown = 1; // unknown
unknownValue = "ABC"; // どの型でも代入可
// let stringValueB: string = unknownValue; // エラー
3-5. オブジェクト型
オブジェクト型は、プロパティ型の集合です。「オブジェクト名.プロパティ名」でオブジェクトのプロパティにアクセスできます。
const person: {
name: string;
age: number;
} = {
name: "taro",
age: 18,
};
person.age = 20; // set
console.log(person.name); // get
taro
「プロパティ名 in オブジェクト名」でオブジェクトが任意のプロパティを持つかどうかは判定できます。
const person: {
name: string;
age: number;
} = {
name: "taro",
age: 18,
};
console.log("name" in person);
true
3-6. オプショナルチェーン
「undefined」のプロパティにアクセスしようとするとエラーになります。
const person: any = undefined;
console.log(person.name); // エラー
「オブジェクト名?.プロパティ名」でプロパティにアクセスすることで、オブジェクトがundefinedの時、エラーでなくundefinedが返されるようになります。
const person: any = undefined;
console.log(person?.name);
undefined
3-7. クラス
「クラス」は、プロパティとメソッドを持つオブジェクト型です。
class NewClass {
property: String;
constructor() {
this.property = "ABC";
}
method() {
return this.property + " from method";
}
}
const instance = new NewClass();
console.log(instance.property);
console.log(instance.method());
ABC
ABC from method
3-8. クラスの判別
「インスタンス名 instanceof クラス名」で、クラスを判別します。
if (instance instanceof NewClass) {
console.log("NewClass")
}
true
3-9. 配列
配列の定義は、次のとおりです。
const numberList: number[] = [0, 1, 2];
const stringList: string[] = ["ABC", "DEF"];
forEach() で全要素を関数処理できます。
const numberList: number[] = [0, 1, 2];
numberList.forEach(function (str, index) {
console.log(index * 2);
});
0
2
4
map() で全要素の関数処理の結果の配列を取得できます。
const numberList: number[] = [0, 1, 2];
const result = numberList.map(function (str, index) {
return index * 2;
});
console.log(result)
[ 0, 2, 4 ]
3-10. テンプレートリテラル
「`」で囲んだ文字列中に「${}」で変数を埋め込むことができます。
const numberValue: number = 1;
const stringValue: string = "ABC";
console.log(`number: ${numberValue}\nstring: ${stringValue}`);
number: 1
string: ABC
4. 演算子
4-1. インクリメント・デクリメント
・A++ : インクリメント
・++A : インクリメント
・A-- : デクリメント
・--A : デクリメント
4-2. 単項演算子
・+ : 加算
・- : 減算
・* : 乗算
・% : 除算
・** : べき乗
4-3. 等値演算子
・== : 等値
・=== : 同値
・!= : 不等値
・!== : 非同値
4-4. 論理演算子
・&& : 論理積
・|| : 論理和
4-5. ビットシフト演算子
・<< : ビット左シフト
・>> : ビット右シフト
・>>> : 符号なしビット右シフト
4-6. 三項演算子
条件 ? 値1 : 値2
5. 構文
5-1. if
const mode: string = "init";
if (mode === "init") {
console.log("init");
} else if (mode === "play") {
console.log("play");
} else {
console.log("else");
}
5-2. switch
const mode: string = "init";
switch (mode) {
case "init":
console.log("init");
break;
case "play":
console.log("play");
break;
default:
console.log("else");
}
5-3. for
const numberList: number[] = [0, 1, 2];
for (let i = 0; i < numberList.length; i++) {
console.log(i);
}
const numberList: number[] = [0, 1, 2];
for (const item of numberList) {
console.log(item);
}
5-4. try〜catch
try {
throw new Error("my error");
console.log("success");
} catch(error) {
if (error instanceof Error) {
console.log(error.message);
}
} finally {
console.log("finally");
}
my error
finally
6. 関数
6-1. 関数
function normalFunction(numberParam: Number, stringParam: string): boolean {
if (numberParam === 1) {
return true;
} else if (stringParam === "ABC") {
return true;
}
return false
}
console.log(normalFunction(1, "ABC"))
true
6-2. アロー関数
const arrowFunction = (numberParam: Number, stringParam: string): boolean => {
if (numberParam === 1) {
return true;
} else if (stringParam === "ABC") {
return true;
}
return false
}
console.log(arrowFunction(1, "ABC"))
true
returnを省略して式を返すこともできます。
const arrowFunction = (numberParam: Number, stringParam: string): boolean =>
numberParam === 1 || stringParam === "ABC";
console.log(arrowFunction(1, "ABC"))
true
7. 型
7-1. 型の定義
type NewType = number;
type NewObjectType = {
numberValue: Number;
stringValue: string;
}
7-2. ユニオン型の定義
type IntersectionObjectType = NewType | NewObjectType;
7-3. インターセクション型の定義
type IntersectionObjectType = NewType & NewObjectType;
7-4. 型の判別
「typeof」で型を判別します。
const value: any = 1;
if (typeof value == "number") {
console.log("number");
} else if (typeof value == "string") {
console.log("string");
}
number
8. ジェネリクス
8-1. ジェネリクス
const genericsFunction = <T>(arg: T): T => {
return arg;
}
console.log(genericsFunction<number>(1));
console.log(genericsFunction<string>("ABC"));
8-2. ユーティリティ型
・Partial<T> : オブジェクト型Tの全プロパティがundefinedになり得る型の生成
・Reqiored<T> : オブジェクト型Tの全プロパティがundefinedになり得ない型の生成
type Person = {
name: string;
age: number;
}
type PartialPerson = Partial<Person>;
/*
{
name?: string | undefined;
age?: number | undefined;
}
*/
type RequiredPerson = Required<PartialPerson>;
/*
{
name: string;
age: number;
}
*/
・Pick<T, K> : オブジェクト型TのプロパティからKのプロパティ以外を除いた型の生成
・Omit<T, K> : オブジェクト型TのプロパティからKのプロパティを除いた型の生成
type Person = {
name: string;
age: number;
}
type PickPerson = Pick<Person, "age">;
/*
{
age: number;
}
*/
type OmitPerson = Omit<Person, "age">;
/*
{
name: string;
}
*/
・Exclude<T, U> : ユニオン型Tのプロパティからユニオン型Uのプロパティを除いた型の生成
・Extract<T, U> : ユニオン型Tのプロパティからユニオン型Uのプロパティ以外を除いた型の生成
type UnionType = 0 | 1 | 2
type ExcludeUnionType = Exclude<UnionType, 0 | 1>;
/*
2
*/
type ExtractUnionType = Extract<UnionType, 0 | 1>;
/*
0 | 1
*/
8-3. keyof
「keyof」は、オブジェクト型のキーを持つユニオン型の生成します。
type Person = {
name: string;
age: number;
}
type PersonKeyType = keyof Person
/*
"name" | "age"
{
name: string;
}
*/
9. モジュール
9-1. ES Modules と CommonJS
モジュール書式には、「ES Modules」と「CommonJS」があります。
・ES Modules
ブラウザで直接動作するように設計されている。
import、export を使用。
・CommonJS
サーバーサイド(Node.js)のニーズにあわせて設計されている。
require、module.exports を使用。
9-2. エクスポート・インポート
「ES Modules」によるエクスポート・インポート手順は、次のとおりです。
(1) 変数や関数のエクスポート。
・other_module.ts
export const exportValue = 1;
export const exportFunction = (num: number) => {
return num + 2;
}
最後にまとめてexportする記述もできます。
const exportValue = 1;
const exportFunction = (num: number) => {
return num + 2;
}
export {exportValue, exportFunction}
(2) 変数や関数のインポート。
・index.ts
import {
exportValue,
exportFunction
} from "./other_module";
console.log(exportValue);
console.log(exportFunction(2));
(3) ビルド
「index.js」と「other_module.js」が生成されます。
$ npm run build
(4) 実行。
$ node index.js
1
4
9-3. バンドル
「バンドル」によって、複数のコードを1つにまとめることができます。これによって、外部スクリプト (node-fetch など) も利用できるようになります。
バンドルして実行する手順は、次のとおりです。
(1) rollupパッケージのインストール。
rollupパッケージは、JavaScriptモジュールバンドラの1つです。
$ npm install rollup
$ npm install @rollup/plugin-commonjs @rollup/plugin-node-resolve @rollup/plugin-typescript tslib
(2) 「rollup.config.js」の追加。
・rollup.config.js
import commonjs from "@rollup/plugin-commonjs"
import resolve from "@rollup/plugin-node-resolve"
import typescript from "@rollup/plugin-typescript"
export default {
input: "index.ts",
output: {
dir: "dist",
format: "cjs"
},
plugins: [
typescript({
module: "ESNext"
}),
resolve(),
commonjs()
]
}
(3) 「package.json」にbundleコマンドを追加。
・package.json (一部)
:
"scripts": {
"build": "tsc",
"bundle": "rollup --config --bundleConfigAsCjs"
},
:
(4) バンドル。
「dist/index.js」が生成されます。
$ npm run bundle
・dist/index.js
'use strict';
const exportValue = 1;
const exportFunction = (num) => {
return num + 2;
};
console.log(exportValue);
console.log(exportFunction(2));
(5) 実行。
$ node dist/index.js
1
4
10. 非同期処理
10-1. 非同期処理
非同期処理の手順は、次のとおりです。
(1) node-fetchパッケージのインストール。
node-fetchパッケージは、非同期処理のパッケージです。
$ npm install node-fetch
(2) index.tsの編集。
import fetch from "node-fetch"
fetch("https://www.google.com/")
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
console.log("start")
(3) バンドルと実行。
$ npm run bundle
$ node dist/index.js