Type Script 入門
概要
TyoeScriptの案件に関わることとなりましたので、Type Scripの使用法をキャッチアップしています。 TyoeScriptの基本的な構文を備忘として投稿します。
なぜType Script が好かれているのか?
- JavaScriptと記法が同じで、そこに型定義が加わっている(勉強コストが低い)
- 変数、関数のパラメーター、オブジェクトの構造まで、厳格な型定義ができる
- 型定義することで、頻繁に引き起こされるエラーをより簡単に、より早く検知できる
- 型定義することで、変数等の役割をより容易に予測できる
※AirbnbはTypeScriptを使用することで潜在的なエラーが大幅に減少すると主張しているそうです。
変数の型定義
変数名に続けて : type とすることで型の定義ができます。
例1)変数を型定義
let firstName: string = 'tadashi'; firstName = 'kouta';
基本的な型の一覧は公式を参考にするといいと思います https://www.typescriptlang.org/docs/handbook/basic-types.html
例2)配列の要素を型定義
let list: number[] = [1, 2, 3]; # 配列の全ての要素がnumber型 let a: [number, boolean] = [1, false]; # 最初の要素がnumber型、2番目の要素がboolean型 let c: [string, string?] = ["hello”]; # 2番目の要素はオプショナル(?)のため、任意項目となる let d: [first: string, second?: number] = ['hoge', 3]; # 各要素にlabelをつけることが可能
例3)TypeScript 4.2の追加機能 これまで、…rest(...string[]など)は最後の要素のみ使用可能でした。
let e: [string, string, ...boolean[]]; # 2つのstring型の要素+boolean型の要素が0〜n個 e = ['hoge', 'foo'] e = ['hoge', 'foo', false,]
TypeScript 4.2では、…rest(...string[]など)が要素の最後以外でも使用可能になりました。
let g: [boolean, ...string[], number]; # string型の要素+boolean型の要素 0〜n個+string型の要素 g = [false, 1] g = [true, 'aa', 2]
一度、型定義をすると改めて型定義することができません
例1)
let firstName: string = 'tadashi'; firstName = 1; # string型ではないため、エラーになります。
例2) 型定義を明示されていなくても、途中で型を変えることはできません。
let firstName = 'tadashi’; # firstNameはstring型が割り当てられる firstName = 1; # string型ではないため、エラーになります。
ちなみに、どんな型でも許容するany型はJavaScriptからTypeScriptへの移行作業中出ない限りは、
使わない方がいいとのことです。型定義で潜在的なエラー削減を目的にTypeScriptを使っているのに、
型定義に怠慢をしてしまうのではTypeScriptを使っている意味がないということですね。
enumの使用
enumを使うことで、意味のある数字をわかりやすい名前で定義することができます。 例)
enum Size { sm = 1, md = 2, lg = 3, } let h: Size = Size.lg
関数のパラメーターを型定義する
引数に続けて : type とすることで型を定義することができます。
また、下のコードの一番右側のnumberはreturnする値のかたを定義しています。
例1)
const sum = (a: number, b: number): number => { return a + b; }let i = sum(5, 10);
何もreturnしない関数はvoid型を定義します。 例2)
console.log(i);function hoge(): void { console.log("hoge") }
オリジナルの型を定義する
既存の型を組み合わせて、オリジナルの型を定義することができます。 例)
type StringOrNum = string | number; # string型、number型を許容する型を作成 let id: StringOrNum = 'Identification number’; id = 1;
insterfaceを定義する
オブジェクトの構造をinterfaceで定義することができます。
typeとinterfaceは機能が似ているのですが、
typeが型の組み合わせで新しい型を定義するのに使う一方、
interfaceはクラス、オブジェクトの構造を定義する
という方針で使い分けるものだと理解しました。
例)
interface Address { zipCode: number; prefecture: string; city: string; } function showAddress(address: Address) { console.log(`${address.zipCode} ${address.prefecture} ${address.city}`) } showAddress({zipCode: 9000000, prefecture: '沖縄県', city: '那覇市'})
参考情報
以下の記事が、とても分かりやすくまとまっていたので一部和訳して引用しております。 https://dev.to/migueldevelopez/typescript-and-why-you-should-type-your-js-project-3amb
Cloud Watch Logs × fluentd × Docker でログの一元管理
概要
AWS の Cloud Watch Logs を使って、EC2上に起動しているDockerコンテナのLogを確認する際、これまでLocalからSSH接続してviで確認していました。
このLog確認の手間を削減するため、DockerコンテナのLogを一元管理できる設定を試してみたので、備忘として投稿します。
実現したいこと
EC2上に起動しているDockerコンテナのLogをCloud Watch Logsに転送してAWS Consoleから各コンテナのLogを管理できるようにします。
技術調査
コンテナからLogをCloud Watch Logs に転送するため、Logging Collectorを使用することにしました。Logging Collectorの候補として次の2つを検討しました
・fluentd
・awslogs
設定の手軽さから awslogs の使用も魅力的だったのですが、awslogsはAmazon Linux向けに開発されたもののようです。
今回の検証は、ubuntuを使います。awslogsをubuntuで使用する場合にはpythonのプログラムを動かさないといけないとの記事を見つけたので断念しました。
今回の実装では fluentd を採用します。
実装概要
実現する内容としては、以下の画像のようなイメージです。
fluentdのコンテナを立て、Log収集対象のコンテナからfluentdのコンテナにログを転送します。
fluentdコンテナはLogを受信したらCloud Watch LogsにLogを転送します。
実装内容
github にfluentdコンテナのDockerファイルを作成しております。
github.com
同じ設定を試してみたい場合は、是非ご参考にしてみてください。
また、修正事項などりましたら、ご指摘いただけますと嬉しいです。
また、Log収集対象のコンテナはdocker-compose.ymlにloggingを追加する必要があります。
tag に設定している値でfuluentdは、どこのコンテナからログが送られてきたか判別します。
logging: driver: "fluentd" options: fluentd-address: "localhost:24224" tag: "backend.log"