2021/5 に全部読みましたが、読書記事(11万文字)を書いたところ、あまりに本文の内容が入ってしまい、著作権的な問題がありそうな気がしたので非公開にしました。
AWS CDKを修正して実行できるようになった
- これはアドカレの記事です
- 経緯・背景
- (CDKに関して)やったこと
- CDKのことを学ぶ編
- 業務のCDKのコードを読んで理解
- CDKのことを十分には知ってなかったので更に知る編
- ついに自分のAWSアカウントで実行してみるぞ
- 本当に自分のAWSアカウントで実行してみるぞ
- 一部修正して反映してみよう (CDK)
- 結局、どのくらい時間がかかったのか
- 感想
これはアドカレの記事です
- これは ドワンゴのカレンダー | Advent Calendar 2022 - Qiita 14日目の記事です。
- なお、25日目にも記事を投稿予定です。(Qiitaで)
- こちらは、大トリにふさわしく、(インパクトのある)高クオリティな記事にしようと思っているので、期待していてください。
- (= つまり、今回の記事のクオリティは高くない…が、(クオリティが低くても)継続が大事 なのでありのままのやり方で、いつもどおり書いてます)
- この記事は 25000文字あります (文庫本50ページ分)
経緯・背景
- (2021/8/23 までに、CloudFormation をとりあえず書いて使えるようになっていた)
- 2022/8/2までに RubyGems (HTML文字列をいい感じにフォーマットする) を公開した
- 元々、2022/9/30までに以下の3つが目標だった
- しかし、結婚式をしたので、RubyGems以外は完遂できなかった (それぞれ半分くらい?)
- 結婚式の後も、新婚旅行と上期の評価資料作りで忙しかった
- 2022/8/23 に CDK に手を付けていたが9/3頃?に中断し、 2022/10/8 に再開した。
- 2022/11/2 までに、 CDK を修正して、実行(反映)できるところまで行った
- その後、社内のLTの準備をしていて、今日(2022/11/26) このCDKのブログを書き始めた。
- 2022/12/12 出来上がった。(19300字)
(CDKに関して)やったこと
- CDKのことを学ぶ
- 業務のCDKを読む
- 業務のCDKを自分のAWSアカウントで実行する (一部分のStackだけ)
- そのStackを一部CDKで変更してみる
CDKのことを学ぶ編
- 5分で理解するAWS CDK - Qiita
CDKはただリソースを定義するだけでなく、プログラム内でテストコードも書くこともできます。
CDKは以下、APP->Stack->Constructの各要素によって構成されています。
- ↓ということらしい
- App スタック依存関係管理
- Stack いつもの
- Consruct リソース
CDKはConstruct Libraryを使用してAWSリソースを定義
High Level Construct(L2) - > 直感的にリソースを定義することができ、デフォルト値や便利なメソッドが定義済み
- クラス名にCfnプレフィックスがついているL1 (L1の方が低レイヤー)
- cdk synth シンセサイザーというか、組み合わせるといういみ
なお、aws ssoを利用している環境の場合、そのまま実行すると、エラーになります。確認すると、本記事執筆時点ではAWS SSOについてサポートされてない様です。この様な場合、環境変数をexportすることで回避できます。
- 親切な情報
- 理想はこのようになることみたい
業務のCDKのコードを読んで理解
- それぞれにREADME.md があって親切
- 公式手順(ちょっと大変みたい…?)
iam identity centerは、コードを使用してiam identity centerセッションを現在のaws cliセッションに関連付けます
iam identity centerブラウザページでは、iam identity centerの認証情報を使用してサインインするように求められます
- そういうブラウザページがあるのね 2022/08/24 0:41
- この↑までは「自動設定」だったとのこと
- 手動設定でもできるとのこと
業務のCDKのコードを読む
- 反映コマンドなどがREADMEに(各スタックごとに)書いてあって分かりやすい!
- 業務のCDKは codefamily, db, elasticache, network, subnet, vpc, web スタックに分かれており、 共通みたいなのがcommon, utility に入っている
- SFTP = SSH File Transer Protocol 2022/08/25 0:04
- https://ja.wikipedia.org/wiki/SSH_File_Transfer_Protocol
- 2001 年までには作られ始めた。 scp より進化してるとのこと
SFTPStack AWS Transfer Familyを使用してS3バケットをバックエンドにしたSFTPサーバを立てるSTACK
CDKのコマンドなど
- cdk commands 2022/08/25 0:19
- https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/cli.html
- これ大事そう (多分全部読んだ)
- import aws_cdk.assertions as assertions
- https://docs.aws.amazon.com/cdk/api/v1/python/aws_cdk.assertions.html
- まぁ、コードの中で分かるかな 2022/08/26 1:26
- 前のqiita を読み直してみる
- まぁ、見様見真似でこの辺をコピペしてきて、カスタマイズするところからかな?
いきなり業務のCDKコードを(自分の個人AWSアカウントで)実行するのは難しかったので、0からCDKを書いて、実行してみた (ような気がしていたが、していなかった) (3ヶ月前にやったことなので忘れていた)
- ec2のなかに CfnVPC作るメソッドがあるおなじみのec2起源なつくり
- ipamもこのメソッドにあるのね
- class CfnVPC (construct) · AWS CDK
- ◎この(業務で使ってる)CDKのバージョンはなんなんだろうなあ
- 現行最新なら 2.38.1かな?
- aws-cdk-lib==2.XX.X と requirements.txt にあった
- $ cdk --version #2.XX.X (build xxxxxxx)
- 名前とかを渡すと vpc が作れる便利なメソッド
- 自分の aws で作ってみたいね
- vpc/vpc_stack.py は単なるクラス、汎用に流用できるものっぽい
- …と思ったけど、そうでもないかな◎
- .bat って rem がコメントアウトなの?
- そうらしい
- こうやって、 vpc, network をカワキリに、業務のCDKを読んでいったのだった
- ◎network ではなく、 vpc/ や subnet/ でつくってる、ってことかな? 2022/08/28 1:08
- やっぱり yml だけで作るのは無理感が高いよなあ(CloudFormationへの思い)
- 自分も別プロジェクトで cFn でsubnet とか作ったので見覚えある内容 というか構成
- でもやっぱり CDKとかにしてくと、サワれる人 どんどん少なくなって、採用がどんどん困難になっていきそう
CDKのことを十分には知ってなかったので更に知る編
cdk の construct とは
- cdk のconstruct ってなんだっけ?
- AWS CDK の3種類の Construct を使ってデプロイしてみた | DevelopersIO
- サンプルコードもあるので、熟練者のcdkがどんなものか見ようかな
- いろんなものが一緒に書かれていた あくまでこの記事の目的のためのサンプルっぽい
- (多分普通は vpc とか subnet とか web(アプリケーション構成単位)で分けそう)
- construct は デプロイするAWSリソース。 だね。 (解決) ココのリソース
- ec2.CfnSubnet(
- やっぱり ec2 以下にサブネット作るメソッドもあるのだった
- 基本的なものは何でもec2のものとするaws
- cdkわかりやすい
- pythonだからかも
- network周り長い 2022/08/28 1:46 要素が多い
- cFnのときより心なしか増えてる気がする
- NAT GW で使う eip
業務のcdkを引き続き読む (/common 編)
- まぁ、 common/ みる 2022/08/29 0:42
- aws kms = Key management service (かなり使いそう)
- kubernetes は eks (そっくり)
- XRegionParam はオリジナルclass だった ので後で読もう
- common_stack.py で 5つ stack class 定義シてる
- Acm とか、自分のawsで実行しても既に取られてるから実行できないかもなあ
- xregion 先に読もうか
- custom resource
- [AWS CDK] APIを呼び出すだけのカスタムリソースならLambda関数は不要な件 | DevelopersIO
AWS CDKの場合、Lambda関数を使わずにAPIを呼び出してカスタムリソースを作成/更新/削除することができます。
皆さんはカスタムリソースを作成することは多いですか? 私はそこまで多くないです。
codecommitの承認ルールテンプレート関連の操作はcloudformationで実装されていません。。。そこで、今回はcodecommitに関する以下の操作をカスタムリソースを介して行います。
- ◎なるほど、こういうやり方があるのね 共有したい
なお、actionで入力する文字列の先頭は大文字ではなく、小文字の場合で入力する必要がある場合がほとんどです。例えば、CreateApprovalRuleTemplate APIを呼び出したい場合は、createApprovalRuleTemplateとなります。
- ☆複雑なlambda 関数が自動で作られて便利 2022/08/29 1:11 (まとめ)
これで「わざわざLambda関数作るのめんどくさいな」からちょっと脱出することができます。
- サーバーレスからLambda関数レスヘ 2022/08/29 1:11
なお、APIを呼び出す前に処理を入れたり、複数のAPIを呼び出す場合はLambda関数を介してカスタムリソースを作成する必要があります。
- x_region_param は、 SSM とかの値を他のregion でも取ってこれるようにしてるようだ
SSM (AWS Systems Manager)とは
- AWS Systems Manager とは? - AWS Systems Manager
- AWSの新サービス SSM を知っていますか? | DevelopersIO (2015/3)
- simple なやつらしい
ssmはamazon ec2 simple systems managerの略で、windowsの構成管理を行えるサービスです。 awsがwindows用のchef serverやpuppet masterを提供してくれる様なものです
- なんか違う感
- AWS Systems Manager の方らしい
- Systems Manager で↓ができるらしい 2022/08/30 0:12
- アプリケーション管理
- 変更管理
- ノード管理
- オペレーション管理
- Quick Setup
- 共有リソース
- systems manager の aws ドキュメントよんだ2022/08/30 0:17
- ASM と SECRETSMANAGER にも対応している、作ってもらった x_region_param (便利メソッド)
- CDKでもお手製便利メソッドが出てくる
ASM (Amazon Secrets Manager) とは
- AWS Secrets Managerを使おう! - Qiita
aws secretsmanager get-secret-value --region ${REGION} --secret-id ${SECRETS_ID}
- みたことあるコマンド
- x_region_param 読み切った 2022/08/30 0:29
- 引き続き行むのCDK読んでく common/
- common_stack.py がある
- 井かの5つのスタックをたててる
- WAFv2 に IP Address tai書かれてる
- common/ はよみきった
(業務のCDKの) utility/ 編
- sftp_stack.py 2022/08/30 23:20
- s3バケットと接続したりする
- class CfnServer (construct) · AWS CDK
(業務のCDKの) web/ 編
- webサーバ周り
- EC2 だけでなく、 ALBとか CloudFront とかも一緒に入ってるメインのスタック
- アプリケーション上の役割別に 7つStackがある
- Backend ヨウのStack は 1つの Class から 複数Stack を作ってる
- config に色々と設定値がかかれてるっぽい auto scaling group のmax capacity とか
- asg.add_user_data( にコマンドで、最初にやることを列挙できて便利
- backend_stack.py と front_stack.py に分かれてる
- class Duration · AWS CDK
- 期間を表すらしい 2022/09/01 0:21
- ec2も少ないパラメータでできるね
- ☆wafもきになるなあ 2022/09/01 0:34
- utc は Coordinated Universal Time
ついに自分のAWSアカウントで実行してみるぞ
- (結局、CDKを0から書くことはしなかった模様)
- 一旦、 vpc を実行 & vpc を修正できたらよしにしようかな
- 多分、aws-cli で操作するのだろう (←違う。cdkコマンドをnpmで入れて使う)
cdkを動かすための勉強
クラメソさんの連載1回めを読む
- まぁせっかくだから ↓の連載を 4までは読んでみようか
- 実践!AWS CDK #1 導入 | DevelopersIO
- summit-online-japan-cdk をやって、環境を整えるのが第一らしい 2022/10/08 21:34
- 実践!AWS CDK #1 導入 | DevelopersIO にkaiteannように、cdk は npm で入れる aws-cdk パッケージで入るコマンドだった 2022/10/08 21:40
- $ npm install @aws-cdk/aws-ec2
今後もこのように利用するクラスによって必要なパッケージをインストールしていきます。
- なるほどなあ
- cdk bootstrap コマンドとか いろいろある ←cfnのためのs3作る
いよいよデプロイです。cdk deploy コマンドを実行します。
- vpc をつくったらデフォルトでは たくさん色々作られるらしい
Construct という単位の基本ビルディングブロック - 作られる各リソースのことだったね
L3: Patterns
- これハツみみ
cdkでは各リソースを表すクラスにcfnというプレフィックスが付いたl1のものが用意されています このクラスを利用することでcfnと同等の制御が可能となります。
NAT ゲートウェイは比較的料金がかかるサービス 。スタックを削除するには cdk destroy コマンドを実行します。
README にも記載していますが node_modules/ は git 管理外としていますので、プロジェクトを実行する際は npm install コマンドを実行して必要なモジュールをインストールしてください。
クラメソさんの連載2-4回めを読む
- 実践!AWS CDK #2 VPC | DevelopersIO
- 普通の構成を作るのに 20買いくらいかかるとのこと
- 20 回くらいかかるかもね。
- まぁ 4買い読んで 実行してみようとして できなかったらさらに読もうかなあ
それでは cdk synth コマンドを使用すると cfn のテンプレートがつくられる 2022/10/11 1:28
snapshot tests。。テスト実行時点で作成されるcfnテンプレート(スナップショット)と事前に保存されているベースラインテンプレートを比較してテスト
- jest を使うのね (TSだからかな)
Ansible のときは「Ansibleに書いたのはそのように作られるのだから、ちゃんとできているかテストは不要よ」みたいなことをどこかで読んだ気がするけど、 でもやっぱり 1個アレができてるか とか書いておくと、意図通りになってるか確認できてよいね
- context は cfnのパラメータ
元やってたことに戻る
- まぁ、何してたのか思い出そう
- cdk が何のコマンドか調べていたのだった
- (業務のCDKのコードの) vpc の readme を読んでてたのだった
業務のCDKのReadme に書いてあるコマンドを理解する
- cdk context --clear とは?
- Concepts - Context|AWS CDK ドキュメント(和訳メモ) を読んでみる
- 少しずつ実際の実行に近づいていってる
cdkは、アカウント内のavailability zoneやインスタンスの起動に使用されるamazon machine image(ami)idなど、awsアカウントからの情報をキャッシュするためにコンテキストを使用します - パラメータトイウだけでなく、キャッシュでもあるのね - だから clear が必要と
このプラクティスは、例えば、新しいamazon linux amiがリリースされ、auto scalingグループが変更されたときに、デプロイメントへの予期しない変更を回避します。 - 途中で変わってしまわないようにという意味もキャッシュにあるのね
cdk.context.jsonは、gitにコミットすることをお勧めします
コンテキスト値は、それを作成したコンストラクトにスコープされ、子コンストラクトからは見えますが、兄弟コンストラクトからは見えません。 - どこかで出てきそう
Python の None の勉強
- python には none というものがあるのね
- 【Python入門】nullオブジェクト「None」とは | 侍エンジニアブログ
Pythonでは他のプログラミング言語とは少し違い、nullというキーワードではなく「None」を使用します。 - > ※ この記事のコードはPython 3.7で動作確認しました。
オブジェクトとnoneを比較する場合は、is演算子を使用することが推奨されています。。。理由は、処理が早く済むことや、noneがシングルトンオブジェクト(そのクラスのオブジェクトは1つのみ、複数のインスタンスの作成が不可能であること)である、などということが挙げられます
- None を print すると None と表示するのが律儀な感じ2022/10/12 23:24
- 他の言語だったら空文字列になりそう
元のzen (cdk context --clear) に戻る
- AWS CDK アプリと呼ぶのね CDKで書いたものを
cdk.context.json ファイル内の情報を表示、管理するには、cdk context コマンドを使用します - ◎そのうち cdk context コマンド使ってみよう 2022/10/12 23:29
保存されているアプリのコンテキスト値をすべてクリアするには、次のようにcdk context --clearを実行します。 - こういうことね (理解できたので目的達成) - > cdk.context.jsonに格納されているコンテキスト値のみ、リセットまたはクリアすることができます。
必要であれば、コンテキスト値の前にスタック名を付けることで、各スタックに異なる値を指定することができます。 - > cdk synth --context Stack1:key=value --context Stack2:key=value Stack1 Stack2
- zen を 読み切った 2022/10/14 0:19 3min
元の 業務のcdk vpc readme に戻る
- cdk diff --profile project_name
- cdk の --profile か…
- 自分で作っておくようだが
- これも知っておこうか
- [AWS CDK(Cloud Development Kit)] 複数アカウント・複数リージョンへのデプロイを管理する | DevelopersIO
複数アカウント・複数リージョンへのデプロイを管理する - むふう
今回はpythonを利用。 - 助かる
- aws-cli のprofile と同じなのね(多分)
- $ cdk init --language python で初期化とのこと
- $ cdk ls
- とは
派生して cdk コマンドの コマンドを一通り知る
CDK バージョンのこと
- cdk コマンドの機能を 実際に叩いて理解する 【 AWS CDK Command Line Interface 】 | DevelopersIO
- (dockerって、変更が入ると、linuxサーバとは別にdocker imageの更新がいるので、手間を感じる)2022/10/14 0:31
cdk 1.12.1 (この記事のcdkコマンドのバージョン)
- いまいくらくらいなんだろう
- 業務の は
- めちゃ進んでるなあ
- ちなみに最新は
- https://github.com/aws/aws-cdk/releases
- 2.45.0 っぽい
- 1.12.1 · Releases · aws/aws-cdk · GitHub
- 2021/5/13 に2.0.0
- 2019.10.17 で 1.12.1 は納得
本当に cdk のコマンドを知ってく
- ls は Stack をリストするらしい
アプリケーションが単一のスタックだけで構成されている場合、スタック名を指定する必要はありません
cdk.json または ~/.cdk.json のいずれかが存在する場合、そこに指定されたオプションがデフォルトとして使用されます
- コミットされてる cdk.jsonにも contextがあるね
- コマンドに node packageを指定する
- --plugin , -pなんてオプションがあるのね
- オプションはそこそこ多いけど、 コマンド自体は少なそう cdk
- cdk.json に "app": "npx ts-node bin/eval-cdk.ts" があると --app指定は要らないとのこと
tree コマンドのこと
tree -L 2 lib/
- せっかくなので、さらに派生して tree コマンドも調べよう
- Layer だろうなあ Limit かも
- 【 tree 】コマンド――ディレクトリをツリー状に表示する:Linux基本コマンドTips(179) - @IT
- やっぱり西村めぐみさんだった(Linuxコマンド解説でおなじみ)
centosやubuntuには、デフォルトでtreeコマンドがインストールされていません。「yum install tree」や「apt install tree」でインストール可能です。インストールの実行にはroot権限が必要です - なるほど 使ってないわけだ
- tree -i で中をたどりながらファイルリストを作れるのね 2022/10/15 7:39
- tree -H で a href リンク集めを作るのに便利なのだ
もとに戻って cdk のコマンド(派生1)を読むぞ 2022/10/15 7:46
- cdk bootstrap がなんかdeploy 前にいるらしい 2022/10/15 7:48
- cdk コマンドの機能を 実際に叩いて理解する 【 AWS CDK Command Line Interface 】 | DevelopersIO を読んでいるところだった
- cdk diff もあって便利 2022/10/15 22:24
lib:constructsの集まりをnpmなどで公開可能なように開発できます
3つのリソースから構成される AWS Construct Library - そういうのを配布できるらしい 2022/10/15 22:41
Apps と AWS Construct Library をうまく組み合わせる
- cdk.context.json がデプロイときに自動で書き込まれるやつ、 cdk.json が開発者が書くやつ
- .cdk.json かも??? つかない気がするけど
context 直下の値が Key として認識されていて、それより下層はすべて Value として扱われるようです。
- cdk diff, cdk deployだけでコードにかいたcontext のセットが優先される context では そこまでみない
cdk doctor 便利そう 2022/10/15 22:53
- バグレポート用のものかも
--profile を説明したクラメソさんを読むぞ
- [AWS CDK(Cloud Development Kit)] 複数アカウント・複数リージョンへのデプロイを管理する | DevelopersIO を読んで、 --profile のことを知るぞ
- まぁ、 --profile については、いい感じに接続するプロファイルを用意して使う という意味だろうけどね
$ cdk deploy Stack-prd-tokyo --profile prd
- こういう書き方のところもあるのね (prd/prod)
- こうして、 --profile ことも理解した僕は、 業務のCDK(vpcの) readme を完全に理解したのだった
- ので、実際に自分のawsアカウントで実行していこう
- 実行して、一箇所変えられるようになったらマスター、おわり
本当に自分のAWSアカウントで実行してみるぞ
結局、自分のawsアカウントで実行するには何が要るのか
- ここまでに読んだものにいいやつがあったから発掘しよう
- [読んだもの] 2022/10/16 16:15
- 業務の cdk の vpc のコード
- 実践!AWS CDK #1 導入 | DevelopersIO (多分これが自分のAWSアカウントでのCDK実行に役立ちそう?)
- summit-online-japan-cdk
- 大変そう(詳細すぎそう)公式だけに
- Concepts - Context|AWS CDK ドキュメント(和訳メモ)
- 【Python入門】nullオブジェクト「None」とは | 侍エンジニアブログ
- [AWS CDK(Cloud Development Kit)] 複数アカウント・複数リージョンへのデプロイを管理する | DevelopersIO
- cdk コマンドの機能を 実際に叩いて理解する 【 AWS CDK Command Line Interface 】 | DevelopersIO
- Releases · aws/aws-cdk · GitHub
- 【 tree 】コマンド――ディレクトリをツリー状に表示する:Linux基本コマンドTips(179) - @IT
- 10記事読んだらしい
- で、どうすればいいか
- 最初のクラメソさんの連載をやっていってみよう
- ◎これを自分のawsアカウントでやっていけばいいのだろう
- この記事をやってみる
- 業務のcdkをcloneして実行してみる
- 業務のcdkを変更して実行してみる
このクラメソの実践記事をやってみる 2022/10/16 16:21
- 言われてみれば、自分の awsアカウントわからないかも
- $ aws-cli がないのでいれる
- node は入ってた
- なぜか cdk も元からはいってた
- $ cdk --version
- ~/devio$ cdk init app --language python
- 実践記事で devio/ というディレクトリでやってみよう、となってる
- 実践!AWS CDK #1 導入 | DevelopersIO をやっていってる
- クラス名にCfnがついてるのがL1だっけ?
- そうです(低レベル)
- ~/devio$ cdk synth
- devio/app.py", line 4, in
import aws_cdk as cdk ModuleNotFoundError: No module named 'aws_cdk' - python -m pip install -r requirements.txt
- 60MBとかある
#vpc=ec2.CfnVPC(self) vpc=ec2.Vpc(self, 'Vpc')
- なんで L1の方は VPCが全部大文字何だろう…
- ~/devio$ cdk bootstrap
- これをやったら S3バケットとかできた
Trusted accounts for deployment: (none) Trusted accounts for lookup: (none) Using default execution policy of 'arn:aws:iam::aws:policy/AdministratorAccess'. Pass '--cloudformation-execution-policies' to customize. CDKToolkit: creating CloudFormation changeset... [??????????・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・] (2/12) 7:48:17 AM | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | CDKToolkit 7:48:23 AM | CREATE_IN_PROGRESS | AWS::IAM::Role | ImagePublishingRole 7:48:23 AM | CREATE_IN_PROGRESS | AWS::IAM::Role | FilePublishingRole 7:48:24 AM | CREATE_IN_PROGRESS | AWS::IAM::Role | LookupRole 7:48:24 AM | CREATE_IN_PROGRESS | AWS::IAM::Role | CloudFormationExecutionRole 7:48:24 AM | CREATE_IN_PROGRESS | AWS::S3::Bucket | StagingBucket
- ~/devio$ cat ~/.aws/credentials で、 aws_access_key_id や aws_secret_access_key がつなげる先に S3バケットや CloudFormation Stack が作られるので、接続先が間違ってないか気をつけよう!
- 間違って作ったときは cdk destroy して、 s3バケットとかをc消せばいいらしい
- でも、結局は消えなくて、management console からけした気がする
:~/devio$ cdk destroy Are you sure you want to delete: DevioStack (y/n)? y DevioStack: destroying... ? DevioStack: destroyed
- 権限が足りないらしい
~/devio$ cdk bootstrap ? Bootstrapping environment aws /ap-northeast-1 failed bootstrapping: AccessDenied: User: arn:aws:iam: :user/superuser is not authorized to perform: cloudformation:DescribeStacks on resource: arn:aws:cloudformation:ap-northeast-1: stack/CDKToolkit/* because no identity-based policy allows the cloudformation:DescribeStacks action at Request.extractError (/home/linuxbrew/.linuxbrew/lib/node_modules/aws-sdk/lib/protocol/query.js:50:29)
- iam user 全権限 AdministratorAccess
- CloudFormation::Stack 多分なまえが CDKToolKit や IAM Policy, Role や S3何かを保存する の三種類を作ってるみたいだね cdk bootstrap すると (全部で12個)
~/devio$ cdk bootstrap ? Bootstrapping environment aws:// /ap-northeast-1... Trusted accounts for deployment: (none) Trusted accounts for lookup: (none) Using default execution policy of 'arn:aws:iam::aws:policy/AdministratorAccess'. Pass '--cloudformation-execution-policies' to customize. CDKToolkit: creating CloudFormation changeset... ? Environment aws:// /ap-northeast-1 bootstrapped.
- cdk destroyしたときに s3は消えなかったけど、 policy role はきえてそう???
- 消えてない気が まぁあってもいいか
- cloud formation の stack ものこってるので消す
- というか、このcfn が他の全てを作ってるのか 2022/10/22 3:45
- cfn のstack の削除の様子ってログでないのかな(ぱっと見つからない)
- 消えたっぽいのでよし 2022/10/22 3:47
改めて cdk synth からやってく
- synthesize に 20秒くらいかかる
- もろもろ(vpc subnet routetable igw eip natgw) 作るのに … 結構かかりそうだなあ
- 20/25 までi wLj i1分20秒くらい
- 20/25 でなかなかとまってる 1分くらい
- なにが思いのかは見れなかった
- =jJ )eつくるのに 3分くらい
- 確かに vpc や eip ができてた
- cdk destroy 8:30 開始 2022/10/22 23:13
- 2分15秒くらいかかった
- nat gateway とか deletedになってた
- cdk destroy で消えるリソースもあるらしい
- 1時間で消えるらしい (deleted になった nat gateway)
- 引き続き 実践!AWS CDK #1 導入 | DevelopersIO を参考に、業務のcdkを実行していっている.(vpc)
- cdk list 10秒くらいかかる
業務のCDKのコードを clone してやってくぞ
- $ git clone @
organization has enabled or enforced SAML SSO. To access this repository, you must use the HTTPS remote with a personal access token or SSH with an SSH key and passphrase that has been authorized for this organization. Visit https://docs.github.com/articles/authenticating-to-a-github-organization-with-saml-single-sign-on/ for more information. fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
- https://github.com/settings/keys で Configure SSO で Authorize すればいいんだっけ?
- まさにそうだった
- git clone 成功
- cdk.json がある階層が実行する階層のようだ (実行時にカレントディレクトリにするディレクトリ)
- cdk synth -> cdk bootstrap -> cdk deploy の順
- なんか ipam-pool がないということで失敗した
- Synthesis time: 14.26s
$ cdk deploy VPCStack: creating CloudFormation changeset... [・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・] (0/3) 11:35:28 PM | CREATE_FAILED | AWS::EC2::VPC Resource handler returned message: "The ipam-pool ID 'ipam-pool- does not exist (Service: Ec2, Status Code: 400, Request ID: Hand lerErrorCode: GeneralServiceException) 11:35:29 PM | ROLLBACK_IN_PROGRESS | AWS::CloudFormation::Stack | VPCStack The following resource(s) failed to create:
- 多分、IPAMPool について知っていくのが次のステップになるだろう 2022/10/23 23:38
IPAMPool を設定するぞ
- どこに設定するのか ipamを 2022/10/23 23:38
- VPC内のIPアドレスを効率的に管理するVPC IP Address Managerが発表されました #reinvent | DevelopersIO
- 手でポチポチと設定して、 そのIDを書いてるだけっぽい 2022/10/24 1:52
- [やること]
- その設定を aws console でみる
- 自分ので設定してやる
- 名前タグがあるようだけど、まぁ、そっちでは指定できなさそうだね 2022/10/24 1:55
- プールの中に小さいプールがあるのね 役割別に 2022/10/24 1:56
- 勉強になる
- vpc に pool を指定できるのね
- ☆このpool を 業務 cdk でどう使ってるのか 2022/10/24 1:57
- → 調べる
- ☆ipam pool は手入力なのかな
- https://ap-northeast-1.console.aws.amazon.com/ipam/home?region=ap-northeast-1#PoolDetails:PoolId=ipam-pool- に pool id があるね
ipam を自分のAWSアカウントに作って、cdk deploy 完遂を目指す
- とりあえず pool 自分のaws アカウントで作ろうか 手作業で
組織の IPAM の委任管理者ではないことを検出しました。IPAM を作成すると、アカウント内のリソースのみが監視されます。IPAM で組織全体のリソースを監視する場合は、委任管理者のアカウントに IPAM を作成する必要があります。委任管理者を設定するには、組織の管理アカウントとしてサインインし、[設定] ページに移動します。 - って出てきて親切なaws
- つくってみた
- プロビジョンとかしなくていいのかな?
- まぁcdkに書いてみよう
- 前回うまくいかなかったコマンドは $ cdk deploy
- vpc/cdk.json に書いた (そこの pool id を読む cdkアプリ が業務の cdk にかかれてる)
- ipam アカンといわれた
- does not exist といわれた
- あるとおもうんだけどなあ
- スコープタイププライベートがダメなのかな
- ipam id と pool id は違うのね
- ipamしかつくってなかった(多分)
プール使用率 このプールにはプロビジョンされた CIDR がありません。
IPAM の Locale とは
- Localが必要と言われた 2022/10/29 0:18
- ipamのlocal を調べないと池なさそうだなあ
- [やること]
- 一般的な ipam local しらべる locale か
- 業務でどうなってるか見る
- チュートリアル: AWS CLI を使用して IPAM とプールを作成する - Amazon Virtual Private Cloud
- 業務のは共有プールだから、いきなりリージョンプールだけがあるのね 2022/10/29 0:47
- じゃあ、自分のでは、トップレベルプールの下に 10. とかのをつくってみようね
- でかすぎるから /24 とかでいいかも
- 割り振りはやはり /24 が基本でやってるぽい
- /17 から /24 が32コとれるのかな いや 128 か
- 2 4 8 16 32 64 128
- やはり 2の7上増えてるね
- 自分ので 10.32.1.0/24 みたいなのをpoolきる
- トップレベルの下にリージョナルで
- cdk deploy うったが synth に 34秒かかった
- 海鮮思いから?
- 最初にcdk deploy コマンド打ってから通るまで何分かかったか書くといいかもね
- The allocation size is too big for the pool といわれた
- allocation size がどこかにあるのね よもう
- ipv4_netmask_length=24, という記載が業務のCDKにあった
- ので、 /23でpool を切ろうと思った
- CIDR をプールに手動で割り当てて IP アドレス空間を予約する - Amazon Virtual Private Cloud
- 10.0.0.0/24 とか /24 で指定するらしい とおった
- https://ap-northeast-1.console.aws.amazon.com/ipam/home?region=ap-northeast-1#PoolDetails:PoolId=
- 保留中のプロビジョンというのは、どこにも割り当てられてない、ってことかな?
- 失敗したプロビジョン (The CIDR does not exist in the parent pool.) になってた
- 親で 10.0.0.0/21 する コは /22 でプロビジョニングしたら、ついに cdk deploy が通った
/vpc$ cdk deploy ? Synthesis time: 14.48s VPCStack: deploying... [0%] start: Publishing [100%] success: Published VPCStack: creating CloudFormation changeset... ? VPCStack ? Deployment time: 42.31s Stack ARN: arn:aws:cloudformation:ap-northeast-1: ? Total time: 56.79s
- https://ap-northeast-1.console.aws.amazon.com/vpc/home?region=ap-northeast-1#vpcs: にできてた
- nat gw がないので料金高くはないのでは 2022/10/30 21:13
一部修正して反映してみよう (CDK)
- [どこを修正できそうか]
- まぁ、pool 変えてみようか
- まえの22でつくられてるな…
- ネットワーク計算ツール・CIDR計算ツール | Softel labs
- 10.0.4.0/22 か にしてみよう(1つ後の帯域)
- ipam-pool- を別にクリックで作った(management console)
- cdk.json のpool ID をかえて、
vpc$ cdk diff Stack VPCStack There were no differences
- むふう
- 何かを変えたら↓になった
vpc$ cdk diff Stack VPCStack Resources [~] AWS::EC2::VPC (Stack名) replace └─ [~] Ipv4IpamPoolId (requires replacement) ├─ [-] ipam-pool-111111 └─ [+] ipam-pool-222222
- いい感じ 日字2022/11/01 22:57
- vpc$ cdk synth
- いざデプロイ
vpc$ cdk deploy VPCStack ? Synthesis time: 13.7s VPCStack: deploying... [0%] start: Publishing [100%] success: Published VPCStack: creating CloudFormation changeset... ? VPCStack ? Deployment time: 54.22s Stack ARN: arn:aws:cloudformation:ap-northeast-1: ? Total time: 67.92s
- 普通におわった
- https://ap-northeast-1.console.aws.amazon.com/vpc/home?region=ap-northeast-1#vpcs:
- vpc id もかわった
- 10.0.4.0/24
- ちゃんとできたのでおわり
結局、どのくらい時間がかかったのか
- (元々、CloudFormation は一通りできる状態だった)
- 時間の計測結果
- CDKの勉強+業務のCDKコード読むのに (大部分はCDK自体の勉強) 317分 (5時間強)
- CDKを自分のAWSアカウントで実行&修正実行してみるのに: 228分 (4時間弱)
- このブログを書くのに: 162分 (2時間半強) (19300字) (URLやスペースも数えると25000字)
- 1分120字、1時間7250字
- 足し合わせると、CDKの修正実行ができるようになるまでに 9時間かかり、 ブログまで入れて全部でも 11時間半強 (707分)
- つまり、丸々一日使えれば半日(一日)で終わる時間なので、普通だった
- (半日でこれくらいできるようになるのが普通な感覚)
- 1日20分なら 35日なので、やはり普通
- 1日20分なら、1ヶ月でこれくらい1技術習得するのが普通
- つまり、丸々一日使えれば半日(一日)で終わる時間なので、普通だった
感想
- コツコツやって、CDKを修正&反映できるようになって良かった
HTMLフォーマッターgemを作った (hitomalu_formatter)
経緯
- HTML文字列をフォーマットしてくれる、最近もメンテナンスされてるgemがなかったため作った
- 特に下記の点を重視した
- 何回もかけても同じ結果になること (span や p や インデントが増えないこと)
できたもの
- hitomalu_formatter | RubyGems.org | your community gem host
- GitHub - t-hazawa/hitomalu_formatter: Format Html String
似たライブラリ
- GitHub - akicho8/html_formatter: HTML自動整形ライブラリ (最終コミット7年前)
このようなフォーマットができます
主なルール
- タグの中身の整形について
- 開始タグから 非空白文字が始まるまでの 空白文字は削除
- 行中(= 行の中で非空白文字で囲まれたところ)にある半角スペースは保持 (ただし、2つ以上連続していたら1つにする)
- 改行や行頭 or 行末の空白文字は、改行前後の行に非空白文字があるなら、半角スペース1つに置換 (非空白文字がない行は削除)
- 最後の非空白文字から閉じタグまでの空白文字は削除
- pre 要素の中は整形しない
- インライン要素の後は 「改行(スペース混じりでも)があれば改行1個にする」「改行がなく、スペースがあればスペース1個にする」(何もなければそのまま)
- インデントはしない
- (これ以外にもルールはあります)
例
- hitomalu_formatter/formatter_spec.rb at master · t-hazawa/hitomalu_formatter · GitHub より抜粋
- (しかしテストコードは expected が改行コードなのでわかりにくい)
例1
<div> <p id="kore_id" hgeg2> nakami </p><span>2つ目</span></div><a href="hoge">fuga</a> <pre> (スペース4つ) (a c) || 人 ←全角スペース </pre> <!-- コメントしてみた --> <saigo>aaaa</saigo>
↓
<div> <p id=\"kore_id\" hgeg2>nakami</p> <span>2つ目</span> </div> <a href=\"hoge\">fuga</a> <pre> (スペース4つ) (a c) || 人 ←全角スペース </pre> <!-- コメントしてみた --> <saigo>aaaa</saigo>
使い方
gem install hitomalu_formatter require "hitomalu_formatter" Hitomalu::Formatter.format('<DIV id=aaa>content</div>') => "<div id=\"aaa\">content</div>"
ポイント
- Nokogiri利用
- なので Nokogiri に似た感じのgem名にしました
- テストケースが44種類あって安心
- すっかりテストありきの人間になりました
- 100万文字で20000ノード程度のHTMLの場合、2分前後、メモリ5GB程度使います。
詳細 (ここから技術勉強ブログ的内容)
やったこと
フォーマッターを作るにあたって
- MacやLinuxの改行コード(\n) と Windowsの改行コード (\r\n) をあわせるのが大事
- シェルで使えるコマンドは速い
- sed の例
- 100万文字から 20000箇所置換するのが 20ミリ秒くらい
- sed の例
- paiza の ブラウザで Ruby を実行できるものは便利
- Online PHP/Java/C++... editor and compiler | paiza.IO
- 試すのも共有も簡単。Nokogiri も require 'Nokogiri' だけで使える
高速化で参考にした記事
Nokogiri の挙動などフォーマッターつくりについて
- 勝手に wbr に閉じタグをつける (wbr は閉じタグを伴わない要素)
- HTML5からは閉じタグを p や li などメジャーな要素で省略できるようになったが、Nokogiri は 中身がないと積極的に省略しがち (なので、中身がない場合は中にダミー文字列を入れて閉じタグをつけさせて、最後に空文字列に置換)
- Nokogiri は 閉じタグと閉じタグの間の \n を消すようなので、一旦 ダミー文字列にして後で置換
- Ruby では "\n" と '\n' では意味が違う (前者が今回必要なもの)
gem にするにあたって
- はじめての自作Gem - シンプルなGemを作成して公開する - Qiita を参考にしました
- git add しないと rake build の対象にならないのがムズい
- git ありきの仕組み
- 作成したgemを扱う際の注意点 - Qiita (神Qiita)
- .gem/credentials を作るには Gem パッケージを作成する (3) パッケージを公開する - まくまくRubyノート。 curl -u するとパスワードを入力できる
感想など
- gemは公開すると、それだけでかなりDLされる (数時間で100など)
業務のJSを1テストケースだけJestにしてみた
経緯
- 業務のJS(結構モダン)をTypeScript にしたい
- テストが全くないので、テストをまず作りたい
- テストフレームワークは流行ってるみたいなのでJestにしよう
- 前回(38日前)、Jest自体は TypeScript の単体テストで Jest 使おう - Qiita をやってみて、一応使えるようになった
- 今回は、実際の業務のコードを1つJest にしてみる
概要
- めちゃくちゃ詰まったポイントがあった
- 業務のコードの拡張子が .js だと、 「ES mocules の import を使いなさい」みたいなError がでたが、 .ts にしたら解消した
- Jest でテストコード(window.alertが文言指定で出るか) 自体は一瞬で書けた
かかった時間
- 5/22, 24 作戦考える (5日間開く)
- 5/28 Jest やりはじめる (~5/30)
- 6/1 import export のエラーに苦しみ始める
- (6/18 まで評価資料5月分の方をする)
- 6/19~6/25 そのエラーに取り組む (1日10~30分)
- 6/26 ~6/29 そのエラーを突破できたので、先を進める
- 6/30 ブログを書き始める
- つまり、2週間弱かな?
- このブログを書くのに 2022/07/05 1:43 まで 6日間、80分かかった
やったこと
- 業務のJSがあるので(いい感じにモジュール化されてる)、それについて https://qiita.com/okazuki/items/991a068892e946531612 (この前やったqiita)の通りやってけば、 test できそう
最終的にいい感じに通った時のコード
- Marumaru という機能があると思ってください
- npm t するとテストが通る (上のqiita 通りに組んだので)
marumaru.test.ts import zembu from "../src/marumaru"; beforeAll(() => { // window.alertをモックにする。Jestではモックにしないとエラーになる window.alert = jest.fn() }); test('test', () => { zembu.add_marumaru('hikisuu1', 'hikisuu2', 'hikisuu3'); expect(window.alert).toHaveBeenCalledWith('ログインしてね'); });
marumaru.ts import $ from "jquery"; import "jquery.cookie"; const add_marumaru = function (hikisuu1, hikisuu2, hikisuu3) { 略 alert('ログインしてね'); }; 略 export default { add_marumaru, add_kakukaku };
- …と、何の変哲もない(?) ES Modulesなコードだった
- しかし、 marumaru.ts ではなく marumaru.js にしてたため、長いこと import 周りで悩んだ
詰まる前編
- marumaru.test.ts に import Marumaru from "./src/marumaru"; とかいたら 問題タブに モジュール './src/marumaru' またはそれに対応する型宣言が見つかりません。と言われたのでts設定をゆるく仕様とおもった
- ↓もしたが、僕の場合効果がなかった
- 多分 TypeScript未対応のモジュールをimportするときのエラー対策 - Qiita を参考に、とりあえず //@ts-ignore をつけたら問題は消えた
- // をつけないといけないのかな? (js難しいポイント)
export のエラー文言が出る試行錯誤編
- npm t したら SyntaxError: Unexpected token 'export' で悩んでる 2022/06/01 0:38
- https://jestjs.io/docs/ecmascript-modules をよめばいいのかな 16m 2022/06/01 0:39
- JestをES6化してimport/exportを使う方法 もやってみた
cross-env編
- Windowsユーザーはcross-envを使うと良いらしい
- そもそもcross-envとはなんなのかを知るぞ2022/06/20 1:00
- Nuxtでcross-envを使い環境ごとに環境変数を分ける - Qiita
- env.development.js (開発環境用ファイル) とかを使うんだね
- 多分、この環境設定ファイルに、ESModulesを使うためのオプションを書くのだろう
- npm install --save cross-env
- なんでも npm にある
- うーん、cross-envの確認方法がほしい
- 内容的には↓に近そう(多分結果的には違った)
にっちも察知もいかないから0からやる編
- ↑↑↑のQiita 自体で練習はできたので、それから、少しずつ、やりたいコードに変えていけば、おかしくなったところがどこか気づける作戦
- tsconfig.json の "module": "commonjs", がだめそう 2022/06/21 22:54
- 最終的には此れで問題無かった 2022/07/04 2:43
- package.json の "type": "module", も 最終的には此れで問題なかった
- 2019.3 と、 かなり最近なんだなあ
// 近しいpackage.jsonのtypeがmoduleなので、このファイルはESMで読み込まれる import './sample/setup/init.js'; // ./node_modules/foo/package.jsonにはtypeが書いてないため、CJSで読み込まれる import 'foo';
とのことなので、 type: module だと、 eS modules になるのだろう ぜ ぜ - まぁ、おいおいわかっていくだろう
- 途中で読んだqiita
- 多分、最初にうっかり CommonJS形式を選んでしまったのだと思う
2022/06/21 23:07
- そうでもないかも
- ターミナルをvscodeで右に表示するとみやすいかも
- ターミナル? PowerShell のスクロール設定がわるい
- キーボードならたしかにこれ Ctrl + PageUp [Powershell]Powershellコンソールで1行ずつスクロールする – エンジニ屋
- スクロールの行数は他のソフトと共通で7ぎょうだった ただ、中割が ないのでPower11hell は特にみにくい(諦め) OR<IOOまぁ、→のスクロールバーをつかめばいい
- ターミナル? PowerShell のスクロール設定がわるい
まだまだ試行錯誤編
- なんか、いけそうな気もしてるたので、なかなか0からというか、上手くいったやつから寄せていかなくて苦労してる
- module.exports を export default { にもどしたら、おなじみの SyntaxError: Unexpected token 'export' がでた。
- 一度諦めてcommonJS形式にしたときの記録
- JSは同じことについて運種類も書き方があって難しい ユーザが必要な機能を次から次に実装していいた結果
- とはいえ、ややこしいだけで普通に習得していけるものなのだろうと思う 難しくて時間がかかるけど
- JSは同じことについて運種類も書き方があって難しい ユーザが必要な機能を次から次に実装していいた結果
- 一度諦めてcommonJS形式にしたときの記録
- やっぱり最初からやろうか。
- 最初から練習でうまくできたqiita をやったら そのまま npx tsc -init したら、かってに module:commonjs になった
- 最終的にもこれでうごいてた
- npx tsc -init
Created a new tsconfig.json with: TS target: es2016 module: commonjs strict: true esModuleInterop: true skipLibCheck: true forceConsistentCasingInFileNames: true
- "module": "es6", / Specify what module code is generated. / にしてみた 2022/06/22 22:52 11m だめだった 2022/06/22 22:52 ES2022でもだめ e
- タいしゅうてきには "module": "commonjs",
モジュールの CommonJS形式と ES Modules 形式
- ES Modules に sが付くとロクからして難しい
- わかりやすいQiita tsconfigのmoduleとtargetには何を設定すればいいか - TypeScript - Qiita
- 短くて分かりや良い生地
- import/export が ES2015 ES modules
- require/exports (CommonJS)
- たったのこれだけだよなあ
再び、上手くいった練習と見比べ
- ちゃんとテストがうごいてる jest_rensyuu と見比べたり、jest_rensyuu に合わせていって、設定には問題なく、コードに問題があることを発見した
- export - JavaScript | MDN
- 書き方が大量にありすぎて難しすぎる js 2022/06/24 1:31
- jest_rensyuu では ES modules で上手くいってるのでこのままでいけそうな気もしなくもない。
- export default と export const で違いがあるらしい (default export, named export)
- 多分、 named export は、呼ぶ側でその名前を指定しないとimport できない
- export default とexport constの違い - Qiita
- 中途半端には jest は es modules export, import に対応してそう 2022/06/25 0:35
- 役立った素晴らしい記事
少し前進
- export const add_marumaru = function (hikisuu1, hikisuu2, hikisuu3) { みたいな形式から export function add_marumaru (hikisuu1, hikisuu2, hikisuu3) { にしたら進みだした
やっと解決編
- ファイルの名前を marumaru.js から marumaru.ts にしたらじごくくの Must use import to load ES Module: C:\Users\tetsuo_yamada\marumaru_jest\src\marumaru.js がたなくなった
- ts-loader みたいなのが挟まってるから?(?)
- やってればおいおい分かるだろう(?)
普通にjestを書いていく編
- referenceerror document is not defined jest
- よくあるエラーぽい
- jest の環境ではそのままだと docuent がないよと。 2022/06/26 21:13
- ぴったりそうな記事
数あるJavaScriptテストツールの中からjestを選んだのは、jest-puppeteer、jest-image-snapshotなどpuppeteer関連で使い勝手が良さそうだったからです。
- puppeteer がいるのかな ?
- 要らなさそうだった 2022/07/05 1:41
作成時にテスト環境としてnode.jsかjsdomを選択していると思います。node.j指定だとこれからのテストでdocument is not definedとエラーになるためjsdomを指定します。
- // testEnvironment: "node",
- testEnvironment: "jsdom",
- なるほど。頼れる
- npm install jest-environment-jsdom がいりそう
alert をテストする編 2022/07/05 1:42
- 素晴らしい記事
- 5分でできた! (本記事の冒頭のコードを書いた)
感想
- JSは書き方がたくさんあってタイへん
この次
- 多分、運用できる状態を整えて、1関数分テストを完備して、導入する
- TSまで行けるか?
- 似た部分が多い関数なのでなんとか集約できるかも
Jest(JavaScriptテストライブラリー)をやってみた
前回: TypeScriptの組み込み方を学んだ(webpackで ts-loader), webpack plugin 色々 - t_hazawaの日記
経緯
- あるプロジェクトのJSをTypeScriptにしたい
- 前回までで、TypeSctipt自体は結構学んだ
- テストがまだ
- Jestやってみた
やったこと
- TypeScript の単体テストで Jest 使おう - Qiita
- jest も npm で入れるものなのね
- この Qiitaのことを自分でもやってみた
- Windows10 VSCode でやってる
npm init -y npx tsc -init npm install typescript せよと言われたのでした npx tsc -init
- npm install ts-node したら npm t (テスト実行コマンド)通った
- テストもテスト対象も src/ に入れたらできた
- やりきった
次
- 実際に、プロダクトのJSをTSにすべく、計画を立てる (どこをやってみるつもりとか)
TypeScriptの組み込み方を学んだ(webpackで ts-loader), webpack plugin 色々
前回: サバイバルTypeScriptを読んだ - t_hazawaの日記
やりたいこと・概要
- TypeScriptになってないが、そこそこJSがモダンなプロダクトがある
- TypeScript を導入したい
- 前回、TypeScript 自体を勉強した
- TypeScript をどう導入するかしらべたぞ
- 大体 webpack で ts-loader
時間まとめ
- (前回までのあらすじ)
- TS自体を学んで 2022-02-23 までにブログにした
- サバイバルTypeScriptを読んだ - t_hazawaの日記
今回
- 2/28-3/7 に組み込み方まなんでいた
- (3/9-3/31 まで評価資料作ってた)
- 今度から、月の最後の2日間を毎月当てようと思う(各月2時間弱)
- 4/1-4/23に続きを学んだ
- 4/24-4/27 にこのブログを書いていたが、その後、4月分の評価資料を作り始めたら、ストップウォッチを使わず、1日にちょこっとずつしか進めなかったので、12日間も評価資料(4月分)を作っていた
- モチベが低い作業はストップウォッチを使わないと本当にほんの少ししかしない(学び)
つまり
- TSの組み込み方の勉強には1ヶ月かかった
勉強したこと (まとめ)
- webpack.js の module: { rules: [ で test で .ts だけを ts-loader に流し込むことができるのだ
- 流し込んだやつを他のJSと一緒にバンドればいいのだ
- 我々の プロダクトは yarn で package.json のことを実行し、そこに "scripts": { "build:prod": "webpack --config webpack.prod.js とかかれてて、webpack を実行してる
- package.json のことも調べた
勉強したこと (詳細)
- 多分、 サバイバル TypeScript には、「tsc コマンドを使えばいいのだ」とだけ書かれていて、 「webpackをこう使うのだ」とまでは書かれて無かったのだと思う
- yarn は 2016年に Facebook が公開したが、 npm と全く名前が似てないのでわかりにくい
- yarn は英語で編糸という意味らしい
- yarn && yarn build:prod みたいなかんじでタスクランナーとして使われる
- 最新版で学ぶwebpack 5入門 - JavaScriptのモジュールバンドラ - ICS MEDIA
- 頼れるサイト
- webpack に集約するのがナウそう
- 最新版で学ぶwebpack 5入門 - JavaScriptのモジュールバンドラ - ICS MEDIA
- 頼れるページ
- フロントエンドは使うものが多くて大変
- バックエンドは言語の公式が力を持つけど、フロントエンドはEcmaScriptしかなく、それがみんなのものだから群雄割拠なのかな
- いつも言われること
二度目以降のビルドは、差分ビルドとして時間が大幅に短縮されます。ビルド短縮のため、webpack-dev-serverもしくは後述のwatch機能は必ず利用しましょう。 "start": "webpack serve"
- 頼れる記事その2
typescriptは高度なウェブアプリケーションの開発で使われることが多く、google社内の標準言語として2017年に採用されるなど、注目が高まっています
- @types/three みたいなのをパッケージ読み込みすると、型情報が得られる
- でも、型情報がもとのパッケージ自体に入ってるのもある
- 2通りある箇所が多くて難しい
webpack 5ではデフォルトで、画像はBase64文字列としてJavaScriptにバンドルできます。しかし、TypeScriptで扱おうとすると工夫が必要です。
画像ファイルの箇所でtype: "asset/inline"を指定します。
- プロダクトの webpack.js っっよんでいった
- 今時のwebpackの構成 - Qiita
この構成で、webpack.configを構成するには、webpack-mergeが必要になります。
- optimize-css-assets-webpack-plugin を知った
- rel=preload - HTML: ハイパーテキストマークアップ言語 | MDN
- mini-css-extract-plugin
plugins: [ new MiniCssExtractPlugin({ filename: 'htdocs/css/[name].css' // ここで設定するfilenameは出力するファイル名
ローダーは記述順の後ろから前に実行される
- terser-webpack-plugin
- webpackの基本だけどハマりやすいentryの設定と[name] - Qiita
- webpackとBabelの基本を理解する(1) ―webpack編― - Qiita
- babel でも TSの変換はできるけど、 webpack で ts-loaderがいいのかな?流行ってそう
- 3つもパッケージインストールが必要なbabel
- 我々のにも "presets": [ ["@babel/preset-env", { "useBuiltIns": "usage", "corejs": 3 }] とだけ書かれたbabelrc がある
- 便利なbabel お試しwebアプリ
- webpackとBabelの基本を理解する(2) ―Babel編― - Qiita
- おなじみの後ろから適用するやつ
useBuiltInsにusageを指定すると、必要に応じてPolyfill(代替コード)に変換してくれます。
バンドる前にraw-loaderを使ってそのファイルを変換してくれないかな。
- 後ろからなので、最終的に先頭のものになる
style-loader: CSSを <style>タグでHTMLに埋め込む
node-sass: Sassをコンパイルするためのツール
- sass->css->style で sassを埋めこめるらしい
- style-loaderの画像埋め込みオプション options.url
- import 'file.scss'; って書かないとバンドられないらしい
- どこかでimortしてつなげることが必要ということ (「接点」)
「MiniCssExtractPlugin」を使って分離手術を実施したいと思います。 - 我々も使ってるプラグイン
- 我々のwebpack.common.js にも全くおなじ
- MiniCssExtractPlugin.loader -> css-loader (url:false) -> sass-loader がかかれてた
webpack.config.jsはNode.jsのファイルなのでrequire文です。
- plugins: [ new MiniCssExtractPlugin({ filename: 'htdocs/css/[name].css' とかけば、 このPluginが補足したものがそっちに図れる
- webpack@4 でCSSを抽出する際は mini-css-extract-plugin を使う - 30歳からのプログラミング
- 最新版TypeScript+webpack 5の環境構築まとめ(React, Three.jsのサンプル付き) - ICS MEDIA に戻ってきた
use: 'ts-loader', らしい npm i -D webpack webpack-cli typescript ts-loader みたいなのが要るらしい
- husky
- git commit にフックするもの
- 必ず使われる、というほどには普及してはなさそう
Jest 編
- TypeScript の単体テストで Jest 使おう - Qiita
- jestは expect(new Greeter('Taro').getMessage()).toBe('Hello Taro'); みたいなかキ方をするらしい
- axios(httpクライアント)を mock
まだ謎なこと
- Jestの運用への組み込み方
次回
- Jest を今のプロダクトのどこに組み込めるか考える
- Jenkins?
- どのように導入しようと考えてるか共有する
- 一箇所で導入してみる
サバイバルTypeScriptを読んだ
経緯
- JavaScript中級者になろうを読んだ
- 本来やりたいのはTypeScript
- 評判が良かったので、サバイバルTypeScriptを読む
- TypeScript入門『サバイバルTypeScript』〜実務で使うなら最低限ここだけはおさえておきたいこと〜
読み終わった感想
読んで学ぶ部分がボリューミーでした (そこだけで18時間) (今日ブログ(5万字メモがある)にします)『サバイバルTypeScript』はJS自体とTS自体を全体的に網羅していてよかったです。 JSの説明については、ところどころ簡潔すぎて、「これだけの説明ではわからなさそう」という感じのところがあったので、そこだけ『JavaScript初心者から中級者になろう』で詳しく知るといいかも、…と思いました。『JavaScript初心者から中級者になろう』は懇切丁寧で著者のuhyoさんの話も面白いのですが、何分量が多いですね。
かかった時間
- 2022/1/29 - 2/22
はじめにから
3000時 最短を目指してるらしい > rubyやpythonなどの動的型付け言語を主に扱ってきており、型をそこまで意識してこなかったので、型システムについて学ぶ必要性を感じている。
あらまし
400時
特徴
1800時
> TypeScriptはMicrosoftにより2012年10月1日に発表されました。 コンパイルがいります > 何よりたのしい たのしみ 型推論のおかげでタイプ量がだいぶ減るらしい > これまでjavascriptに型がないことにより悩まされてきた"実行してみないとわからない"恐怖から解消され、プログラミングを楽しくできます JavaScriptはTypeScriptの一部 500時
誕生の背景
> 代わりに、大規模開発の一部はtypescriptが引き受けることになったのです 今日は補助的な道具の上まで 2022/01/29 14:20 今日はおわり 13:15に始めたので確かに一時間くらい 、 続き 2022/01/30 11:30 6300じ > 1997年に、Microsoftが企業向けウェブメーラーとして、Outlook Web Access 2000を市場投入しましたが、これはJavaScript製のウェブアプリケーションでした。現代の我々からすると意外かもしれませんが、この時代のJavaScriptはまだサーバーと通信することができませんでした。そこで、Microsoftはこのアプリのために、後のXMLHttpRequest(XHR)となるXMLHTTPという機能をInternet Explorerに追加したりもしました > google mapの成功を目にした開発者は、ブラウザさえあれば他に何もインストールする必要がないアプリケーションをユーザーに提供できるウェブアプリケーションにより一層の魅力を感じるようになり むしろ、なぜネイティブアプリはあんなにインストールに時間がかかるのだろう 2022/01/30 11:42 > 2005年には、javascriptアプリケーションフレームワークの先駆けであるprototype.jsがリリースされました。翌年にはjqueryがリリースされ、その後しばらくして、2009年にangularjs、2010年にbackbone.js > 2009年に発表されたcoffeescriptです。coffeescriptはrubyのような簡潔な文法でコーディングできることが魅力の言語で、サーバーサイドフレームワークのruby on railsにもフロントエンド開発用言語として正式採用されました。coffeescriptにはclass構文があり、 > 2012年に発表されたのがtypescriptです。 > 当時、人気を博していたcoffeescriptがjavascriptの文法とはドラスティックに異なる独自路線を打ち出したのに対し、typescriptはjavascriptの文法を拡張するに留める「javascriptのスーパーセット言語」としての戦略を採用しました > typescriptが誕生当初に掲げていた3大特徴のうち、モジュール性はjavascriptの仕様にも盛り込まれ、その部分ではtypescriptは優位性を失いました。 スーパーセット もじゅーる 型
エコシステム
2000時 2022/01/30 12:05 > 静的型検査での同様な立ち位置の技術としてflowが挙げられます > flowには独自の言語がなく、あくまでjavascriptにコメントのような型アノテーションを追加しただけになっています > これは不具合が含まれた製品がリリースされることが少なくなるということを意味します。。。これが型指定が多少面倒でもtypescriptやflowを導入する理由の一部となっています。 > トランスパイラはtypescriptの他に、coffeescriptやdartがあります > トランスパイラの一種にbabelというツールがありま す モジュールバンドラのwebpack, parcel > タスクランナーは、ある決められた処理を実行しやすい形にまとめて、実行の順序などを意識せずに実行できるようにするツールです。gulpやgruntなど > パッケージマネージャー npmや、npmを拡張したyarnが使われています。 > コードフォーマッタ よく使われるのが、Prettier(プリティア)と、ESLint(イーエスリント) Prettierはコード整形を主目的としています。一方ESLintはコードの間違いなども指摘してくれます。 2022/01/30 12:33 よみおわ
なぜ使うべきか
2022/02/01 0:38 https://typescriptbook.jp/overview/why-you-should-use-typescript
4000時 (1200時引くといい全体から) > airbnbによると、typescriptを使っていたらairbnbの38%ものバグを未然に防げたと見る分析を発表しています。 > 静的チェックがあるおかげで、typescriptで検出できる類のバグはテスト工程から省略できるのは確かです > typescriptの場合はひとまずjavascriptとして書き始め、少しずつtypescriptを学んでいき、徐々にtypescriptの恩恵を最大化するようにコードを手直ししていくといったアプローチが可能です > typescriptにはjavascriptにはない数多くの機能がありますが、どれも選択的に導入していくことができます。 過去のesにもトランスパイルできるし、ESNextもどんどん取り入れてるらしいTS 新しいAPIは過去のesバージョンではつかえないとのこと > もし、古い環境で新しいAPIを使う必要がある場合は、core-jsなどのポリフィルを併用することで解決することができます。 プログラム言語人気ランキング9位 https://insights.stackoverflow.com/survey/2020#most-popular-technologies PHPのひとつ下
静的型付け
2400時 > 静的型付け言語は「コンパイル時」に型が定まる。 静的型付け言語にはコンパイルがあるんだね > おかしな代入を早期発見できるというのが、typescriptを始めとした静的型付け言語の大きな利点になるわけです めったに通らないパスでも確実に検出できてすごい 2022/02/01 1:14 > 動的型付け言語では書く必要がなかった型注釈を、typescriptでは基本的には変数ごとに書いていくことになります 過去には静的→動的→静的という変遷があった
ECMAScript
2022/02/01 1:18 4200時 まぁ今日はここまで読めばいいかな > netscape社は、javascriptを標準化するために、国際規格策定団体ecmaインターナショナルに依頼します。 javascriptが商標というのも一因だと考えられています javascriptは当時sunが所有する商標でした。その後、権利はoracleに引き継がれます。 > ecmascriptの規格番号はecma-262です。他にもjson(ecma-404)やc#(ecma-334)などがあります stage3 になったあとにやっぱやめた、にはならないのかな? > ecmascriptが決めるクライアントサイドjavascriptの仕様は部分的です > JavaScriptのうちブラウザ仕様に関する部分は、HTML Living Standardが決めています。ブラウザでJavaScriptを使うと、触れることになるのがwindowオブジェクトやHTMLDivElement、ローカルストレージなどのAPIです。これらはHTML Living Standardと呼ばれる規格が定めています。この規格はEcmaインターナショナルとは異なる標準化団体WHATWGが策定しています。 > 「javascript」と一言で言っても、複数の規格で構成されているわけです > 主要なブラウザの内部を分解すると、レンダリングエンジンやjavascriptエンジンと呼ばれる部品の単位があります > JavaScriptエンジンには、主要なものでV8、SpiderMonkey、JavaScriptCoreがあります。 > 有名なレンダリングエンジンは、Blink、Gecko、WebKitがあります > Google ChromeはBlinkを、SafariはWebKitを組み込んでいます。 > OperaのレンダリングエンジンもPrestoでしたが、Blinkに変更した経緯があります。 > 同じブラウザブランドでも、iOS版のブラウザのレンダリングエンジンはWebKitです。たとえば、Google ChromeはBlinkを採用していますが、iOS版のGoogle ChromeのレンダリングエンジンはWebKitです。これは、iOSのレンダリングエンジンにWebKitだけが独占的に利用を許されているためです。 Firefox-Gecko-SpiderMonkey いかにもapple製なJavaScriptCore やはりJSはLinuxほどは面白くないのでは? 2022/02/01 1:44 やっぱり結局はプレゼンテーションのところだけ感がある ヨミオワ 2022/02/01 1:48
射程
2022/02/01 22:12 4000時 > typescriptを学んだらどのようなソフトウェアを作れるのか ついさっき思ったことを説明し始めててすごい tsはもちろん node.jsでも使えるよ > バックエンド言語はjava、ruby、phpなどの多数の競合があるものの、typescriptもサーバーサイドプログラミングのひとつの選択肢になります。 > 両方でtypescriptを採用するメリット > プロジェクトで扱う言語が1つでよい バックエンドに向いてるのかな? > モジュールを共有できる テストが倍にならない フロントとバックでモジュールはどのくらい共通するのかな > その言語のエコシステムや実務上のベストプラクティス、言語の細かい癖や陥りがちな罠などまで、しっかり理解した実践レベルに到達しようとなると、多くの学習時間を要します > デスクトップアプリケーション。。windowsやmacos、linux向けにデスクトップアプリケーションを作る場合もtypescriptが使えます。デスクトップアプリケーションをjavascript、html、cssの技術スタックで開発できるelectronを用います。 > electron+typescript製の著名なアプリとしては、slackやmicrosoft社のvs codeがあります なるほど > cliアプリケーション。。コマンドラインツールの開発もtypescriptで行えます。サーバーサイドjavascript実行環境のnode.jsとtypescriptを組み合わせて開発します。 > CLIアプリケーションフレームワークには、Heroku製のoclifなどがあります Google製のzxを用いると、シェルスクリプトの代わりにTypeScriptを使うのもしやすくなります。 なんでもTypeScript > Next.jsと親和性の高いVercelのServerless Functions、静的サイトホスティングで有名なNetlifyのNetlify Functions、世界90カ国194の都市にエッジを持つCDN CloudflareのCloudflare Workers > typescriptでもiacを行えます。awsのインフラ構成を自動化するツールにaws cdk(cloud development kit)があります。これはtypescriptをサポートしています たしかに > AWSやGoogle Platformなど複数のクラウドベンダーに対応したインフラ構成ツールとして、Pulumiもあります > TerraformはHCLと呼ばれる独自言語で記述するのに対し、PulumiはTypeScriptなので、TypeScriptプログラマーにとって手が届きやすいツールです。 > google spreadsheetなどには、javascriptで機能を拡張する仕組みが備わっています。それをgoogle apps scriptと呼びます 自動化とかできるらしい > typescriptで書いたコードはjavascriptにコンパイルすれば、google apps scriptで利用できます > ブラウザ拡張はjavascriptで書くことができます。typescriptで書いたコードもjavascriptにコンパイルすることで、ブラウザ拡張として動かせます いろんなところに使える JavaScript > TensorFlow.jsはGoogleが開発した機械学習ライブラリです。Brain.jsはニューラルネットワークのライブラリです。 > WebAssembly(WSM)はブラウザで動くアセンブリー言語です。WSMはJavaScriptよりも高速な処理が必要とされるところで用いられます。WSMのプログラムはC言語やC++、Rustといったシステム言語で開発されることが多いですが、TypeScriptでWSMを開発できるようにする試みも出てきています。その筆頭がAssemblyScriptです。 2022/02/01 23:09 > Javaのキャストみたいなのはないよasは違うよ。instanceof Interfaceはできないよ。
作って学ぶ編
一通り React, Next.js, Jest(テスト) Prettier(整形), eslint(リンター)できるといいかも
eslintって小文字なんだ全部
開発環境
2000文字 一旦、今日は読むだけ読んで、明日やってみよう > ブラウザはJavaScriptからHTMLを操作する必要があるのでDOM APIがありますが、Node.jsにはありません。代わりにNode.jsには、サーバーサイドのさまざまなリソースを制御する必要があるので、ファイルシステムにアクセスするAPIやHTTPサーバーを建てるためのAPI、プロセスを起動したり終了したりするAPIなどがあります。 なるほど。結構別物なのでは? > Node.jsは、JavaScriptをサーバーサイドで動かすことを目的に開発されたソフトウェア なんでもJavaScript の一環なのだ Linux にも brew があるらしい
簡単な関数を作ろう編
2000時 今日はここまで読もう 明日やってみよう > コンパイラが指摘する問題点をすべて解消する作業のことを「コンパイルを通す」といいます。 懐かしい作業なのだ VC++ よみおわ 2022/02/02 0:27 ●では実践しよう 2022/02/02 22:04 まずbrewを入れましょう https://tech-blog.cloud-config.jp/2019-07-19-homebrew-on-wsl/ Homebrew ホームディレクトリにパッケージをインストールできる(sudo不要) > 使用しているディストリビューションでパッケージ化されていないソフトウェアもインストール可能 sudo apt update&&sudo apt upgrade したが、いま 45分経過して snapd 212 43分で 213くらいのパッケージをDLしたようだ 2022/02/02 23:03 58 分 apt upgrade がおわった 2/03 23:10くらい もういっかい sudo apt update && sudo apt upgrade してみよう チェックに割と時間がかかるね いや、 12個本当に更新があったようだな… 1分くらいでおわった slはいった 2022/02/03 23:46 ●サバイバルTypeScriptにもどる 2022/02/03 23:48 https://typescriptbook.jp/tutorials/setup brew install node@16 に10分はかかってる 2022/02/03 23:57 12分くらいでおわった なんか入らなかったみたいなので sudo apt install nodejs してる satoshi_takami@sa-takami-dl:~$ node -v v10.19.0 めちゃふるかった 再度 brew install node@16 2022/02/04 0:04 echo 'export PATH="/home/linuxbrew/.linuxbrew/opt/node@16/bin:$PATH"' >> ~/.profile して wsl立ち上げ直したら 16.13.2になった tsc -v できた 2022/02/04 0:07 多分環境つくりできた 2022/02/04 0:07
2022/02/05 0:10 今日の実践開始
Reactでいいねボタンを作ろう
突然React 2022/02/05 0:19 まず読むか > reactはfacebook社が開発したuiを作るためのパッケージ Meta > uiが複雑になるとreactなしではコードの記述量が増大したり、可読性が悪くなったりと難易度が上がります > なんといっても、uiが今どのような状態なのかを管理するのは、プログラマが把握しきれない複雑さになることがあります Reactはパッケージ React の必要性わかった > Reactでは 見てのとおり、どのように表示するかの部分はなく、「このような表示になってほしい」という目標だけが書かれています。 宣言的なコードつよい(命令は大変) > ページもコンポーネント > コンポーネントベースのメリットは、同じコンポーネントを再利用できる点です オープンソースのコンポーネントも数多く公開されています yarn 一瞬ではいった 2022/02/05 0:40 npxコマンド…? 2022/02/05 0:40 https://zenn.dev/ryuu/articles/what-npxcommand > npxコマンドを使うことでインストールされていないコマンドであっても自動的に探してインストール、実行まで行ってくれます。 実行したあとはパッケージの除去まで行ってくれるため、環境が汚れる心配はないそうです。 インストールするまでも無いけど手軽に試したい、環境を汚したくないそんなニーズに なるほど npx create-react-app like-button --template typescript 3分くらいかかったけど yarn start react が ローカルサーバを用意してるのかな > このHTMLに見える部分はJSXと言われるものです。JSXはJavaScriptを拡張した言語で、JavaScriptの中にXMLを直接書けるようにしたものです。 > jsxを戻り値にする関数をreact用語で「関数コンポーネント」と言います。 画面の部品をコンポーネントにしておくと、再利用できたり変更が一箇所で済んだりと、開発や保守がしやすくなります。 今回作るボタンは次の図のようなシンプルなものです。 まで 2022/02/05 1:08 2022/02/07 0:43 機能はお腹がいたかったので休み なんと.tsxの最後にcssをかける 駆けなかった App.cssだった cursor: pointer; で手のマークになる よく見る useState 関数 > setCountにはcountの値を変更する関数が代入されます。 > 次に、span要素をクリックしたときに、countの値を増加するhandleClick関数を実装します。 むずかしい こーどよんだらよくわかった まぁわかったかも 2022/02/07 1:00 17分しかやってないのでもう少ししよう Next.js を調べるだけしようかな https://qiita.com/Yuki_Oshima/items/5c0dfd8f7af8fb76af8f 語気がつよい 2022/02/07 1:02 けどしっかり書かれてそう > Next.jsはモダンかつ強力なフロントエンドフレームワーク React との関係はなんなのかな? Reactの上にさらに載ってる感じみたいだね > Next.jsはサーバーサイドレンダリング(SSR)やファイルベースルーティングなど多くの機能をゼロコンフィグで提供してくれます > 開発会社Vercelが同名のプラットフォームVercelを展開しており、デプロイ/ビルド/配信までを一気通貫に提供 > Reactをベースにしている以上、Next.jsを使うべきかの判断はReactとの比較がポイント Reactを強化したようなものなのかな? 2022/02/07 1:06 こういう5つの観点というか考慮ポイントがあるのね 何を採用するか > next.jsはアプリケーションを事前にページ単位でレンダリングします。クライアントからのリクエスト時にレンダリングするのがssr(server side rendering)と呼ばれる機能です。またビルド時にレンダリングする機能もあり、ssg(static site generation)と呼ばれます。 サーバで処理するのね Next.js は、で、Reactに近いと Reactは クライアントでうごく > またurlごとに個別のhtmlが生成されるのでseoに有利です。 HTMLがあると安心(?) > 実用上リクエスト時までページの(静的な)内容が確定しないことはまれです ログイン部分はJSでつくろうね 30分したのでおわり 2022/02/07 1:13 さて、具体的にssr/ssgを同実装するのかを から > getStaticProps(SSG) を exportするだけ > getServerSideProps(SSR) getStaticProps() を実装して export async する props: { } の中にあるのを function Blog が処理するっぽい ☆ Next.js の方が SSG だからナウいし、早くてSEO的によさそう! つい今日、Amazonが SSRして撃はやって記事をみたし SPAは表示までおそそう (謎のスプラッシュ挟むサイト多いし) Next.js はルーティングがファイルのあり方に対応してて楽ちんらしい > _app.tsxや_document.tsxは特殊なファイルで、URLには紐づけられません。これらはアプリケーションのエントリーポイントとしてReactのContext Providerを記述したり、HTMLのヘッダーを記述するために使います。 なるほど > pages/post/[pid]/[comment].jsに対して/post/abc/a-commentというURLでアクセスすると { "pid": "abc", "comment": "a-comment" } > next.jsの開発サーバはソースコードの変更を検知して、stateを保持したまま変更があった個所だけを更新してくれます。これにより、開発体験が大幅に向上します。例えば、フォームに入力した内容を保持したままタイトルのfont-sizeを変更することなどができます うむう > Next.jsでコンポーネントを書く際は常に関数コンポーネントに名前を付けてデフォルトエクスポートするようにしましょう。 > Next.js 10.0.0から専用の画像コンポーネントが追加され、配置されるサイズに応じて元画像をトリミングして配信してくれるようになりました。必要なサイズのデータだけをダウンロードするので画像の表示を大幅に高速化できます > レスポンス表示で幅が小さくなった場合も自動でそのサイズにトリミングした画像を生成してくれます。 すごそう > 手書きでwebpackの設定を追加していくとしてもwebpackの設定ファイルを直接書き換えるよりはるかに楽です Reactで細かいwebpackの設定をする際にnpm ejectしてwebpack.config.jsを編集することになりますが、かなり難しい作業です。 > 動的インポートしたコンポーネントはクライアントサイドでレンダリングされるため、実質的にReactと同じように処理される ページ全体を SSGで作るには Next.js はいいんだろうけど、部分的な置き換えには使えなさそうな気がしてきた (React はどうだろう??) > Next.jsサーバへリバースプロキシ(next start) 完全な静的リソースを生成してwebサーバから配信(next export) > SSRを全く使わないならnext exportコマンドでReactと同じように静的リソースを生成することもできます。あとはそれをwebサーバに返してもらうだけです 2020年12月のQiita ヨミオワ 2022/02/07 18:45 きりいいのでおわろうかな
ーーー 2022/02/08 19:09 サバイバルTypeScriptに戻る
https://typescriptbook.jp/tutorials/jest Jest…は会社のプロダクトでやってる気がするからいいかな
Prettier 編 2022/02/08 19:10
https://typescriptbook.jp/tutorials/prettier
これはやりたいなぁ VSCodeで https://www.digitalocean.com/community/tutorials/how-to-format-code-with-prettier-in-visual-studio-code-ja ググって一番上にでてきた 4ふんやった あと26ふん VSCodeのPrettier は 1850万インストール 普通にフォーマットできた 2022/02/08 21:11 jsにもcssにもつかえるよ .prettierrc.yml とかをつくろうね やりきった 2022/02/08 21:16 次が何かみるだけしようかな
●eslintへん2022/02/08 21:17
https://www.google.com/maps/@34.6827335,135.188615,926m/data=!3m1!1e3?hl=ja eslint prettier 違い 2022/02/08 21:17 https://qiita.com/soarflat/items/06377f3b96964964a65d これを読もうかな 2022/02/08 21:18 まぁ、おわり 2022/02/09 22:06 よみはじめ > eslint --fixでコード整形ができる がraibaる > 何故eslintだけではなくprettierも利用するのか > eslint自体の説明は記載しておりません むふう > 読み方はプリティア 基本、フロントエンドだけに対応なプリティア > npm install prettier@2.3.0 --save-dev 開発環境で使いたいものだもんね > ファイルを上書きするために--writeオプションをつける。 prettier app.js --write > eslintでもeslint --fixでコード整形ができるが、prettierの方がコード整形が優れている > eslintと比べて手軽で確実に整形できる。。eslintでは整形できないコードを整形できる。。以下のような一行の文字数が長いコードはeslintでエラーが出力されるが、整形はされない。 つよい > 上記のような整形をしてくれれば、複数のメンバーがエラーに対する独自の修正を適用し、更新するたびに差分が出てしまうような事態を防ぐことができる。 > eslint --fixは設定に該当したエラーのみを整形する。そのため、設定次第ではコードを整形しきれない。Prettier はデフォルトのスタイル(整形ルール)が存在する ゼロコンフィグ > eslint(ESLint 本体) eslint-config-prettier(ESLint のフォーマット関連のルールを全て無効にする、要は Prettier が整形した箇所に関してエラーを出さなくなる) http://tempest.blog.jp/archives/50414936.html rc は run command らしい package.json は scripts フィールドに、 実行コマンドをカケるんだね > gitにはコミット前に指定のスクリプトを実行できるpre-commitフックと言う仕組みがある > npm install husky@6.0.0 lint-staged@11.0.0 --save-dev > husky(Git のコミット時やプッシュ時に指定したコマンドを実行できる) lint-staged(Git のステージングに追加されたファイルにのみに ESLint などのリントを実行できる) > npm set-script prepare "husky install" package.json の "scripts" フィールドに "prepare" を追加するコマンド > prepareはnpm installなどを実行時に自動で実行される。 読み終 21分かかった もうちょっとしよう 2022/02/09 22:28 eslint typescript vscode で検索 一番上の https://qiita.com/yuma-ito-bd/items/cca7490fd7e300bbf169 をやってみよう 2020/8/30 あんまりVSCode のことは載ってないかも? VSCode の ESLint も 1850万インストール Prettier とかなり同じ 自動でならないが? 30分たったので、明日はこれが自動で整形されるようにしよう2022/02/09 22:36 2022/02/12 0:19 機能は会議がおおかったのでスキップなのだった ESLint と Prettier を同時に format on save したいが動いてないだった あのqiitaではうまくできないので、他の情報源を使うことにする vscode eslint 動かない で検索 2022/02/12 0:26 https://note.kiriukun.com/entry/20190817-eslint-not-working-in-vscode むずかしい https://iwb.jp/vscode-editor-eslint-error-reasons/ なるほど https://qiita.com/genbu-jp/items/a48bcb9df209b71c2de3 eslintは結構めんどくさいようだ prettier は簡単 2022/02/12 0:35 > eslintは、javascriptのための静的解析検証ツールでコーディング段階でソースコードの不整合などをチェックすることができるソフトウェアです まぁ、一箇所に集約した方がかなり楽だからね きっと高度なことをしてるんだろう 難しいせいで小言をいわれた > eslintは解析検証ツール > npmは、node package managerのことです > node.jsのバージョンを容易に切り替えられるnvm-windowsを導入します。 eslintのために npm を入れるために node を入れるために nvm-windows をいれる 四段重ね (Prettier は1段) 集約のためには仕方ないね > nvmは、node version managerのことです > eslintプラグインは、eslint本体とvs codeを繋げてタイムリーなコード入力サポートやエラー検出を実現します。 nvm use 16.14.0 exit status 1: ?A?N?Z?X???????????????B 読めない 管理者権限か? (エスパー) 管理者権限だった まぁ、 管理者権限で cmd 立ち上げて nvm use したら vs code terminal でも nvm list * 16.14.0 (Currently using 64-bit executable) ってなったんでいいんでない この 5 LGTMのqiitaの おかげで format on save できました 46分2022/02/12 1:03 2022/02/12も腹痛でやすみ
●husky編 2022/02/13 15:02
途中でみたぞ やっぱり作りかけなので調べてやるぞ husky vscode husky はvscodeの拡張機能にはなさそう なんかhusky は windowsだとバグだらけっぽい https://tamiblog.xyz/2021/02/17/post-1667/ まぁ、このあとに VSCode ESlint でやってみましょう まぁ、husky のこと調べてそれで一旦はよしとしようか https://qiita.com/tags/husky あんまり流行ってない気が LGTM 51とか https://www.vektor-inc.co.jp/post/use-husky/ これを読んで勉強したことにする2022/02/13 15:22 > husky は npmパッケージ > こういった小さな積み重ねが開発スピートに関わってきますので、大事ですね。 一応 vs codeでやってみようか npmコマンド まぁ vscodeだとなんか動かなかったみたいだ まぁ読んだのでおわり 最初はここまでカチカチにしなくてイイダろう
「読んで学ぶ」編 2022/02/13 15:30
> 本章の流れは、コード上の小さいパーツから大きいパーツに行くように構成しています。 値など 2022/02/13 19:23 https://typescriptbook.jp/reference/values-types-variables > letは変数の初期値なしで変数定義できます。初期値なしの変数の値はundefinedになります。 > 基本はconstで変数宣言をして必要な場合にのみ、letを使うのがオススメです 安全なconst varの問題点 https://typescriptbook.jp/reference/values-types-variables/vars-problems グローバルで var innerWidth を定義すると window.innerWidthになる > letやconstはグローバルなスコープで定義されることはない > JavaScriptで宣言された変数はスコープの先頭で変数が生成されます。これは変数の巻き上げと呼ばれています Cは戦闘でしか宣言できなかったね JSはしらんかった > varでの変数巻き上げでは参照エラーとならないため、意図せずにundefinedの値を参照し予期せぬバグが発生する危険性があります。 letとconstでは、宣言前の変数を参照するとReference Errorが発生します。 var x = 1; { console.log(x); } はエラーにならないが var x = 1; { console.log(x); let x = 2; } は巻き上げがあるのでエラー let, const はブロックスコープだから上書きしにくい 型推論まできた https://typescriptbook.jp/reference/values-types-variables/type-inference 17min 2022/02/13 19:40 > let x = 1; // let x: number = 1;と同じ意味になる 型推論は静的型付け > javascriptのプリミティブ型の1つ目の特徴は、値を直接変更できない そうなんだ > オブジェクトには、値を後で変更できるというミュータブル特性(mutable) > 文字列や数値などのプリミティブ型は、プロパティを持ったオブジェクトとして扱えます。。プリミティブ型をまるでオブジェクトのように扱えるのはjavascriptの特徴 > javascriptには、プリミティブ型をオブジェクトに自動変換する機能があります。この機能はオートボクシング(autoboxing)、自動ボックス化 > bigint型: 9007199254740992nのようなnumber型では扱えない大きな整数型。 しらないぷりミティブ型があった
論理型まできたぞ
2022/02/13 19:52 29min TypeScriptの型推論とかは、この7つの型の識別しかしないのかな? > TypeScriptには大文字で始まるBoolean型がありますが、これとbooleanは別の型です。 30分立ったのでおわり 2022/02/13 19:53 数値型から再開 2022/02/14 23:00 当然ながら、JavaScriptのことは、ほぼすべてJS中級者でみた 桁区切りのアンスコはどこで区切ってもいい Number と numberは別よチュュ位シてね > 整数について言うと、他言語の64ビット整数型の範囲より狭いので注意しましょう。 > 0.1 + 0.2は0.3になってほしいところですが、計算結果は0.30000000000000004になります 0.1 + 0.2 === 0.3; //=> false > ちなみに、2進数で有限小数になる0.5や0.25などの数値だけを扱う計算は誤差なく計算できます。 0.5 + 0.25 === 0.75; //=> true > 整数の計算は誤差が生じない > (110 * 11) / 10 === 121; //=> true > 小数計算の誤差問題を包括的に解決したい場合は、decimal.jsのような計算誤差がないパッケージを使うのも手です。 > javaなどの言語では、ダブルクォートで文字列リテラル(string型)を表現し、シングルクォートで文字リテラル(char型)を表現するといったように、使うクォートで型が変わります。 > またバッククォート(`)を使っても文字列型になります。 > 'He said "madam, I\'m Adam."' シングルクォートでも \' が使えるJS > ダブルクォートとシングルクォートを使った文字列リテラルは、文字列の途中で改行できません。改行を入れたい場合は、\nなどの改行シーケンスを入れる必要があります。 > バッククォート`で囲んだ文字列はテンプレートリテラル(template literal)と言います。テンプレートリテラルは、改行と式の挿入(expression interpolation)ができます。式の挿入は${式}のように書きます。 > `現在、${count}名が見ています。` > 基本的に"を使用する。文字列の中に"が含まれる場合は'を使用する。文字列展開する必要があるときは`を使用する。 nullがたまできたが、まだまだ方があるなあ 2022/02/14 23:17 TSのもふくめ15こあるみたい > typeof null; //=> "object" > 戻り値のない関数はundefinedになりますが、TypeScriptで戻り値なしを型注釈で表現する場合、undefinedではなくvoidを用います。詳しくは関数の説明をご覧ください。 > undefinedは「値が代入されていないため、値がない」、nullは「代入すべき値が存在しないため、値がない」という微妙な違い > もしどちらを使うべきか迷ったらundefinedを使っておくほうが無難です > nullは自然発生しない。undefinedは言語仕様上、プログラマーが明示的に使わなくても、自然に発生してくるものです。 > undefinedもnullもプリミティブ型の値という点は共通していますが、undefinedは変数でありnullはリテラルです。 > JSON オブジェクトプロパティの値にundefinedを用いたとき、そのオブジェクトをJSON.stringifyでJSON化したときに、オブジェクトプロパティは削除されます。一方、プロパティの値がnullのときは、JSON化したときに値が保持されます。 > console.log(JSON.stringify({ foo: undefined })); {} console.log(JSON.stringify({ foo: null })); {"foo": null} > 特にこだわりがないのなら、typescriptではnullは使わずにundefinedをもっぱら使うようにするのがお勧めです。 > 実際にtypescriptの開発チームでは「nullは使わない」というたった1行のシンプルなガイドラインを示し、数多くの開発者が参加しやすくなるようにしています。 undefined はそこら中で発生するので、undefinedに統一するのが簡単 2022/02/14 23:41 30分読んだのでおわり null/undefined まで 今日6項目進んだ あと178項目ある このペースだと30日かかる うーん、速度アップがいるかも…??
ーーーー
2022/02/15 22:29 残り178項目
加速する 1日25項目 今日は配列リテラルまで > Rubyのシンボル的なことは、JavaScriptやTypeScriptでは文字列を用いて解決します。 bigint const x = 100n; > bigintリテラルをTypeScriptで用いるには、コンパイラーオプションのtargetをes2020以上にする必要があります。 > const y = BigInt("9007199254740991"); BigInt(100) でも 小数はBigIntにはないよ 自動キャストのことが型強制(type coercion) Stringとかはラッパーオブジェクトで自動ボックス化で活躍 ラッパーオブジェクト型じゃなくてプリミティブ型をつかってくのがよさそうだね いま 4つ読んだ2022/02/15 22:50 > TypeScriptでは暗黙のanyを規制するオプションとして noImplicitAny が用意されています。tsconfig.json にて noImplicitAny: true を設定することで、TypeScriptが型をany型と推測した場合にエラーが発生するようになります。 > 理由なくanyを使うのは問題ですが、どうしてもanyを使わないとならない場面や、型安全性を妥協した上で、まずは動くコードを形にすることを優先するといったこともありえます。anyをどこまで許容するか、型チェックをどこまで厳格にするかは、チームの熟練度やプロジェクトの方針によるところが大きいです。 > 実際に慣れない頃はコンパイルエラーが出ている原因を調べて解消するのに1日を費やす場合もあります。 > 「がんばらないTypeScript」 オブジェクトまでで7つおわった あと18 > オブジェクト型には、クラスから作ったインスタンスだけでなく、クラスそのものや配列、正規表現もあります。 jS中級者なので知ってる話がおおい 結構はやい > オブジェクトリテラルがあるおかげで、JavaScriptでは自由度の高いコードが書けるようになっています。 > JSONはJavaScript Object Nation Nationって何? 1ページが短いのではやいかも 800文字くらい 25項目なら 20000文字 文庫本40ページ分 > let box: { width: number; height: number }; みたいに型注釈する ; がポイントっぽいかな? > // 型エイリアス type Box = { width: number; height: number }; let box: Box = { width: 1080, height: 720 }; もある > let calculator: { sum(x: number, y: number): number; }; > let calculator: { sum: (x: number, y: number) => number; }; もある > let box = { width: 1080, height: 720 }; で勝手にnumber になる (型推論) > メソッドの場合は引数の型注釈は必要です。 > let foo: Record; stringがキーで、 numberがバリューなプロパティを何個もいれたオブジェクトを定義できる オブジェクトの型注釈 https://typescriptbook.jp/reference/values-types-variables/object/type-annotation-of-objects は大事そうだった あと 14項目 > let obj: { readonly foo: number; }; とかある readonlyの項目長い > let obj: Readonly<{ a: number; b: number; c: number; d: number; e: number; f: number; }>; で、全プロパティ readonly な a,b,...f プロパティをもつオブジェクトをつくれる > ユーティリティ型 > let size: { width?: number }; オプショナル あと11 2022/02/15 23:28 > let obj: { [K: string]: number; }; で、キーが string, 値が numberなプロパティをいくつでもつけられる > インデックス型のフィールド名の型はstring、number、symbolのみが指定できます。 TypeScript特有の事項が多くなってきた > let obj1: { [K: string]: number }; let obj2: Record ; おなじ > const dangerousButton = Object.create(button); 複製用メソッドがある(中級者にもかいてあったかも) > JavaScriptの開発には次のような要件がありました。ブラウザで動く言語で、構文はJava風に。しかし、Javaほど大掛かりでないようにと。そして、開発期間はというと、10日と逼迫したものでした。 > JavaScriptの開発にあたり、Selfという言語の影響があったとEich氏は言います。 > JavaScriptのプロトタイプベース採用の背景には、言語をシンプルで柔軟なものにしたいという考えが根底にあったわけです。 その結果いろいろな書き方が生まれた(これが柔軟らしい) > let b: Object; let c: {}; という書き方もある > Object型はインターフェース 自動ボックス化で プリミティブ型もOKになる あと7つ 2022/02/16 0:02 分割代入も入れ後にできる 分割代入に名前の付け替えがある > canada: { name: canadaName }, https://typescriptbook.jp/reference/values-types-variables/object/destructuring-assignment-from-objects オブジェクトのキーと変数名が同じだと、変数名を指定してその名前のキーにその値をいれられる > const pikachu: Wild = { name, no, genre, height, weight }; > JavaScriptのオプショナルチェーン?. 便利そう > const title = book?.title; titleがなかったら undefined になる > 関数を呼び出すときにもオプショナルチェーンが使えます。関数に使う場合は、引数カッコの前に?.を書きます。 > const result = increment?.(1); > 配列要素を参照する際にもオプショナルチェーンが使えます。要素を参照する場合は、カギカッコの前に?.を書きます。 > const title = books?.[0]; Null合体演算子と組み合わせると便利 > const title = book?.title ?? "デフォルトタイトル"; > for (const prop in foo) { propにはキーが入る > if (Object.prototype.hasOwnProperty.call(foo, prop)) { ってやると安全 > for (const [key, value] of Object.entries(foo)) { > for (const key of Object.keys(foo)) { > for (const key of Object.values(foo)) { でも hasOwnProperty いらず 構造的部分型にきたぞ 2022/02/16 0:36 https://typescriptbook.jp/reference/values-types-variables/structural-subtyping 構造的部分型で置換できちゃうから、うっかり動いてしまわないように注意、ってことでは? 終わり 2022/02/16 0:41 2時間強かかってるが? ーーー 明日は 配列の型注釈から https://typescriptbook.jp/reference/values-types-variables/array/type-annotation-of-array if-else 文まで 型がおわったらJSっぽいからすぐ終わっていきそう
2022/02/16 17:44 再開
2022/02/16 18:21 ほんとうに再開 > let array: number[]; > let array: Array; 2通りある > プロジェクトでは統一すべし > JavaScriptの配列はオブジェクトであるため、配列の中身が同じでも、オブジェクトのインスタンスが異なると==では期待する比較ができないので注意が必要です。この点はPythonのリストと同じです。 > このような配列の中身を比べるための演算子やメソッドはJavaScriptにはないため、中身を比較したいときにはlodashのisEqualなどのパッケージを使うのがお勧めです。 > ブラケット[] > JavaScriptの配列では、存在しないインデックス番号でもアクセスできます。その場合でも、JavaScriptではエラーになりません。得られる値はundefinedになります。 なんか、他言語いずれかでのことを知ってる人向けの資料だね > string[]型から0番目の要素の型はstringになります。 > 要素アクセスで得た値はstringとundefinedどちらの可能性もありながら、TypeScriptは常にstring型であると考えるようになっています。そのため、要素アクセスでundefinedが返ってくる場合のエラーはTypeScriptでは発見できず、JavaScript実行時に判明することになります。 > この問題を指摘してもらうようにするには、コンパイラーオプションのnoUncheckedIndexedAccessを有効にします。 > string | undefined型のままではtoUpperCaseなどの文字列型のメソッドは呼び出せません。そこで、if文で変数が文字列型だけになるように絞り込みます。 複雑になってきた > if (typeof character === "string") { > 配列要素へのアクセスを安全にするために、noUncheckedIndexedAccessを有効にしておくことを推奨します。 > const nums: readonly number[] = [1, 2, 3]; > const nums: ReadonlyArray = [1, 2, 3]; 型アサーション as number[]; 分割代入辺 2022/02/16 20:38 戻ってきた https://typescriptbook.jp/reference/values-types-variables/array/destructuring-assignment-from-array > const [one, two, three] = oneToFive; > noUncheckedIndexedAccess では number | undefined になってしまう > ネストした要素の分割代入の書き方は、ネスト構造と一致するようにブラケット([ ])を重ねます。 > const [, , , four, five] = oneToFive; > const [one, ...rest] = oneToFive; 残りが残余パターンでまとまる > 残余部分の型は配列のnumber[]になります。 ぜんぶ JS中級者でみたメソッドなのだ > reverse 配列の要素を逆順に並び替える 便利そう > const copy = [...original]; // コピーを作る > const reversed = [...original].reverse(); あと19項目 2022/02/16 20:48 (ループする方法から) > for (const value of arr) { 配列だと要素が入る > forEachには戻り値がありません。for文などと異なり、breakやcontinueは使えません。 > arr.forEach((value, i) => { インデックスもとれるぞ > const arr2 = arr.map((value) => value + value); > mapではbreakやcontinueは使えません。 > const concated = [...arr, ...arr2]; 連結も簡単 > 似たシンタックスとして分割代入で使われる残余パターンの構文がありますが、異なる構文なので注意が必要です。 分割代入の残余パターンとは別 > TypeScriptの配列の型は共変(covariant)です。 > 共変とはその型自身、もしくは、その部分型(subtype)が代入できることを言います 共変であれば、Animal型の変数にはAnimal自身とその部分型のDogが代入できます。 > type Animal = { isAnimal: boolean }; type Dog = { isAnimal: boolean; isDog: boolean }; > TypeScriptが健全性(soundness)と利便性のバランスを取ること目標にして、型システムを設計しているためです。配列が非変であると健全性は高くなりますが、利便性は下がります。 危険だが、便利らしい > const list: [number, string, boolean] = tuple(); 配列の各要素の型ッ指定できるタプル > function tuple(): [number, string, boolean] { > 配列の型はarray(T[]), generic(Array )というふたつの書き方がありました > const [num, str, bool]: [number, string, boolean] = tuple(); > const [, , bool]: [number, string, boolean] = tuple(); 分割代入をかつよう > Promise という型の変数はawaitをその前につけるとTが取り出せる > const tuple: [string, number] = await Promise.all([ takes3Seconds(), takes5Seconds(), ]); なるほど > Promise.all()は先に終了した関数から順番に戻り値のタプルとして格納されることはなく、元々の順番を保持します。 あと15項目 2022/02/16 21:03 次は列挙型 enum > enum Position { TypeScriptにしか enumはないのかな? そうらしい > 値は0からの連番になります > let position: Position; > enum Position { Top = 1, // 1 とかもある > enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT", } もあるぞ 列挙型はTypeScript独自なのでオススメできないらしい > 型に関する部分を除けば、JavaScriptの文法から離れすぎない言語になっています。 > 文字列列挙型は例外的に公称型になります。 > type YesNo = "yes" | "no"; とかオススメらしい type 宣言 キーワードさらっとでてきたっぽい > const yes = Symbol(); const no = Symbol(); type YesNo = typeof yes | typeof no; とかも > type Position = typeof Position[keyof typeof Position]; むふう 次はユニオン型 あと11項目 2022/02/16 21:10 > |は型のリストの冒頭に置くこともできます。型ごとに改行するときに、列が揃うので便利です。 type ErrorCode = | 400 | 401; 値を型にすることもかのうだったね > type List = (string | number)[]; () をつけましょう > 絞り込み(narrowing) > if (typeof maybeUserId === "string") { tsでおなじみの構文 > 判別可能なユニオン型 > オブジェクト型からなるユニオン型を絞り込む際に、分岐ロジックが複雑になる場合は、判別可能なユニオン型を使うとコードの可読性と保守性がよくなります。 > if (status.done === false && "progress" in status) { とかでも型を絞り込める この項目長い 4800字 なんか大物が続きそうだ > タグ付きユニオン(tagged union)や直和型と呼ぶこともあります。 > 各オブジェクト型を判別するためのプロパティ(しるし)を持つ このプロパティのことをディスクリミネータ(discriminator)と呼ぶ > type InProgress = { type: "InProgress"; progress: number }; とか というか、 > type UploadStatus = InProgress | Success | Failure; type InProgress = { type: "InProgress"; progress: number }; 後で中身を定義してもいいんだね 文字列もリテラルがたナンだね 文字列 数値 論理値 > nullと非nullの関係にある型もディスクリミネータになれます。 > type Result = | { error: null; value: string } | { error: Error }; 片方はnullにならないなら オブジェクト型とかでもいいみたい undefined もあるよ > ディスクリミネータを変数に代入し、その変数を条件分岐に使った場合も、型の絞り込みができます。 型のある言語でここまで型のことをちゃんとやってたかな?? でもそういう機能もあったような気もする オブジェクトの定義を合成させるインターセクション型 2022/02/16 21:28 > type ThreeDimensionalPoint = TwoDimensionalPoint & Z; > プリミティブ型のインターセクション型をつくることもできますが、作るとneverという型ができます。意外なところで役に立ちます。 Required Partial 便利そうだね > type Optional = Partial<{ index: number; > type Parameter = Readonly ; あと8項目 次は型エイリアす e0c 2022/02/16 21:32 > type StringOrNumber = string | number; さっきからたくさん出てきてる > stringなどのビルトインの型 > // リテラル型 type OK = 200; > // 関数型 type CallbackFunction = (value: string) => boolean; 関数型もまだ染み付いてないけどきいじそう > 型エイリアスは同じ型を再利用したいときに使うと便利です。型の定義が一箇所になるため、保守性が向上します。 読みやすくもなる(ことがある) > TypeScriptには、型推論を上書きする機能があります。その機能を型アサーション(type assertion)と言います。 > const strLength: number = (value as string).length; numberにも 同じ名前のメソッドがあると 型に従ってエラーを出せずピンチ > const strLength: number = ( value).length; > アングルブランケット構文はJSXと見分けがつかないことがあるため、as構文が用いられることのほうが多いです。 やはり複数の書き方があるJSの子供であるTS > それでも自分の書いた型アサーションが正しいという場合は、unknown型を経由することで上のようなエラーを出さないようにもできます。 > 型アノテーションはキャストではないため、TypeScriptでは型アノテーションをキャストとは呼ばないことになっています。実行時に型変換をするには、そのためのロジックを書く必要があります。 コンパイルときにしか聞かないからキャストではないとのこと > 型に関することはできるだけ、コンパイラーの型推論に頼ったほうが安全なので、型アサーションは、やむを得ない場合にのみ使うべきです。 型アサーションを使う必要が出てきたら、それよりも先に、型ガードやユーザー定義型ガードで解決できないか検討してみるとよいでしょう。 > let value: number; がカた注釈 > オブジェクトリテラルの末尾にas constを記述すればプロパティがreadonlyでリテラルタイプで指定した物と同等の扱いになります。i > const pikachu = { name: "pikachu", no: 25, genre: "mouse pokemon", height: 0.4, weight: 6.0, } as const; 全部を一括でこていできて便利 あとご項目 2022/02/16 21:41 次は definite assignment assertion > let num!: number; // ^definite assignment assertion > この変数はこの型であることが確実であることをTypeScriptコンパイラに伝えるということです。 > console.log(num! * 2); // エラーにならない // ^非Nullアサーション > // 型ガード if (typeof num === "number") > return value !== null && typeof value === "object"; > ここで説明したのはJavaScriptのtypeof演算子です。TypeScriptのtypeof型演算子については、typeof型演算子の説明をご覧ください。 別の typeofがあるらしい > JavaScriptにはグローバルオブジェクト(global object)と呼ばれるオブジェクトがたったひとつ存在します。ブラウザではwindowオブジェクトがグローバルオブジェクトです。 全てのグローバル変数を司るグローバルオブジェクト > グローバル変数は、グローバルオブジェクトのプロパティになります。 > 日付のDateクラスや、デバッグに使うconsoleオブジェクトなどの組み込みAPIはすべてwindowオブジェクトのプロパティです。 > レキシカルスコープ(lexical scope)変数とは、関数を定義した地点から参照できる、関数の外の変数を言います。 > ブロックスコープはif構文などのブレースにも作用します。条件分岐の中で変数宣言された変数は、条件分岐の外からは参照できないので注意しましょう。 > ローカル変数を宣言する場合は、letやconstを用いますが、これを書き忘れた変数代入は、グローバル変数になってしまいます。 TypeScriptでは変数宣言されていない変数に代入しようとすると、コンパイラが指摘してくれます。 > else ifのようにelseとifの間にはスペースが必要です。 > JavaScriptのif-elseは文です。式ではないので、条件分岐を直接変数に代入することはできません。 居ょの文おわり 2022/02/16 22:24 明日は this引数まで
wwwwwwww
2022/02/17 21:47
よんでこ https://typescriptbook.jp/reference/statements/ternary-operator から > for-of文 - 拡張for文 for-of が 拡張for文 ということらしい > for (const [index, word] of words.entries()) { インデックスと値を一緒に取る方法 > switch (条件) { case 値A: 値Aの処理; break; switch のあとに { があって結構珍しい書き方? > switchのフォールスルー問題 PHPと同じかな? > TypeScriptでは、コンパイラオプションnoFallthroughCasesInSwitchをtrueにすると、フォールスルーを警告するようになります。このオプションは有効化しておきましょう。 fallthrough できなくなるらしい > caseの変数スコープはない > case 1: { { で囲める case > 例外として投げるオブジェクトはErrorオブジェクトを使うのが一般的です。 Error 以外も投げれそう > Errorオブジェクトを使ったほうがコードの読み手に意外性を与えないからです。加えて、スタックトレースが追えるのはErrorオブジェクトだけだからです。 意外性最小を目指そう > TypeScriptではcatchの変数の型はデフォルトでany型になります。 > JavaScriptとTypeScriptではcatchは1つしか書けません。JavaScriptでエラーの型によってエラーハンドリングを分岐したい場合は、catchブロックの中で分岐を書く方法で対応します。 > } else if (e instanceof RangeError) { > 唯一never型は代入できます。 > const foo: never = 1 as never; > never型はどんな型にも代入できます。 > never型の「値が無い」とはどういうことでしょうか。たとえば、例外が必ず発生する関数の戻り値です。戻り値は絶対に取れません。そのため、戻り値の型はnever型になります。 > 終了しない関数も戻り値がnever型になります。 ずっとまわりそう never型ながい 3600時 void型はundefinedが代入できますが、neverは値を持てません。 意味的に戻り値でのvoidとneverは、戻り値が無い点は同じです。関数が終了するかが異なります。voidは関数が最後まで実行されるという意味です。neverは関数の処理が中断、もしくは、永遠に続くことを意味します。 網羅性チェックに使えるらしい 上級ュ者むけっポイ感じする > 一歩進んで網羅性チェック用の例外クラスを定義するのがお進めです。このクラスは、コンストラクタ引数にnever型を取る設計にします。 > 網羅性チェックを例外にしておくと、未使用変数についてのコンパイルエラーが発生しなくなります。 バッドプラクティス感はある > このような型チェックのコードを型ガードと呼びます。 > if(typeof month === "string") よくみるやつ > date != nullの型ガードを追加することで型エラーを解消できます。 | null のばあい > 特定のクラスのインスタンスであることを判定する型ガードを書きたい場合はinstanceofを利用します。 クラスの判定もできるTypeScript > 特定のクラスのインスタンスであることを明示せず、in演算子でオブジェクトが特定のプロパティを持つかを判定する型ガードを書くことで型を絞り込むこともできます。 > if ("castMagic" in player) { > 型ガードはインラインで記述する以外にも関数として定義することもできます。 > function isWizard(player: Player): player is Wizard { 便利 > unknownはどんな型も代入できる型 > unknown型はanyを除いて他の型には代入できない > 同様にunknown型は、プロパティアクセスや関数呼び出しがコンパイルエラーになる。 あと 16項目 2022/02/18 1:06 any, unknown型はどのような値も代入できます。 any型に代入したオブジェクトのプロパティ、メソッドは使用することができます。 > noImplicitAnyがあります。既存のJavaScriptのプロジェクトをTypeScriptに置き換えていくのではなく、スクラッチの状態からTypeScriptで作るのであればこの設定を入れるとよいでしょう。 僕も知ってる設定 > 関数宣言 定まさし あと14項目 2022/02/18 1:11 引数の型注釈を省略した場合、コンパイラーはany型と暗黙的に解釈します。 コンパイラーオプションのnoImplicitAnyをtrueに設定することで、引数の型注釈を必須にできます。 型推論で ユニオン型になることも > 関数式を用いて関数を定義するには、function式を用います。関数式は式なので、関数の終わりにはセミコロンを書きます。 ; をつけるだけで function敷になる > アロー関数は関数式に比べて短く書けるのが特徴的です。引数が1つだけの場合は、引数のカッコが省略できます。 色んな書き方があるJS > さらに、関数内のコードが式1つだけの場合は、ブレースとreturnが省略できます。 シンタックスシュガーだらけ > アロー関数でカッコを省略した記述をした場合には、引数と戻り値のどちらも型注釈を書けません。 noImplicitAnyが有効になっていても、関数引数に直接アロー関数を書く場合は型注釈を省略できます。 TypeScriptでは、関数の型を宣言できます。関数の型の宣言とは、関数の実装を示さずに、関数のインターフェースを定義することです。 type Increment = (num: number) => number; > しかし、関数宣言(function文)の型注釈には使えません。 なんでや function敷には使える > 関数の型宣言を型注釈に使った場合、関数の実装側の引数と戻り値の型注釈は省略できます。 実際のコードでは、省略形で書くのが一般的です。 > TypeScriptでは、アロー関数構文で関数の型を宣言する方法とは別に、メソッド構文でも関数の型を宣言できます。 > // メソッド構文による型宣言 type Increment2 = { (num: number): number; }; > 一般的には、アロー関数構文で型宣言します。アロー関数構文のほうが短くシンプルだからです。 > メソッド構文による型宣言は、オーバーロード関数の型宣言に使われることがあります。 > TypeScriptでは、関数の実装から関数の型を宣言できます。関数の値に対してtypeof型演算子を使います。 > JavaScriptの関数宣言と関数式の違いが現れるひとつの例は巻き上げ(hoisting)です 関数宣言には巻き上げがあり、関数式には巻き上げがありません。 このコードは、hello関数の定義行より前でその関数を呼び出しているのに、エラーにはならず問題なく"Hello World"が出力されます。これは関数宣言には巻き上げがあるためです。 残り9項目 ニ地2022/02/18 1:36 他の言語では関数は特別な立ち位置のことがあります。ある言語では、同じ名前の変数を定義してもエラーにならないのに対し、同じ名前の関数定義はエラーになります。またある言語では、関数を変数に代入できなかったりします。 JavaScriptの関数は値です。つまり、PHPのような他の言語と比べると特別扱いの度合いが少ないです。 JavaScriptで関数の再代入によるバグを未然に回避したい場合は、constと関数式を組み合わせます。関数式については後述します。 ちなみに、TypeScriptではコンパイラーが重複した関数宣言を警告してくれるので、バグの心配はありません。 関数は値なので、関数名のスコープも変数と同じようにスコープの概念があります。たとえば、関数スコープの中で定義された関数は、そのローカルスコープでのみ使うことができます。 https://typescriptbook.jp/reference/functions/function-is-an-object 1行だけでめちゃみじかい 50地 あと6項目2022/02/18 1:49 TypeScriptで戻り値がない関数の戻り値を型注釈するにはvoid型を用います。void型は関数の戻り値を型注釈するためにある特別な型です。 > JavaScriptでは引数が少ない時はその引数にはundefinedが渡され、引数が多い場合は余分な引数は無視されますがここはTypeScriptとJavaScriptとの大きな違いです。 > 引数を省略したいことがあります。そのときはオプション引数とデフォルト引数を使用することができます。 > 可能であればデフォルト引数の使用を検討してください。 > オプション引数は必ず最後に書かなければいけません。つまり、次のようにオプション引数より後ろに普通の引数を書くことはできません。 デフォルト引数とは、関数に値が渡されないときやundefinedが渡されたときに代わりに初期化され使用される値のことです。なおnullが渡されたときはデフォルト引数は適用されませんので注意してください。 > const p0: Point = { x: 0, y: 0, }; function distance(p1: Point, p2: Point = p0): number { オプション引数と比べてもより簡素に書けるようになります。 また、オプション引数と異なりデフォルト引数は値が渡されたときも渡されなかったときも意図する型(この場合Point型)が入っているのでオプション引数と異なり処理の分岐が不要になります。 > さらに、デフォルト引数があることでデフォルト引数を受け付けている引数は型推論が効き型を書く必要がなくなります。 なるほど、だから引数に方がかかれてないことがあったのね > function distance(p1: Point, p2: Point = inverse(p1)): number { もかのう > デフォルト引数はオプション引数と異なりその引数を最後に書く必要はありません。 イタレリツクセリなデフォルト引数 > distance(undefined, q2); > 関数をデフォルト引数として使うときは非同期の関数を使うことができません。 こういうところで化まりそう でもまぁ エラーメッセージがあるので大丈夫とは思う 引数の個数が決まっていない引数のことを可変長引数(variable length arguments, variadic arguments)といいます。JavaScriptでは可変長引数は残余引数(rest parameter)と呼びます。 function func(...params) { 受け取った残余引数は配列になります。 残余引数は必ず最後の引数でなければなりません。残余引数を複数持たせることはできません。また、残余引数の後に普通の引数を置くこともできません。 JavaScriptに組み込みのメソッドにMath.max()があります。これは、引数に与えられた数値の中から最大値を返します。この関数は残余引数を要求します。 関数呼び出しのときにひとつの配列にまとめて渡すことはできません。 配列を余剰引数に渡す場合は、スプレッド構文(spread syntax)を用います。スプレッド構文は...と書きます。 const highest = Math.max(...scores); 残余引数もスプレッド構文も...と同じ表記ですが、スプレッド構文は配列を引数にバラすものです。 アロー関数以外の関数とクラスのメソッドの第1引数はthisという特殊な引数を受けることができます > 引数のthisを指定することによって意図しないメソッドの持ち出しを避けることができます。 そうなんや おわり 2022/02/18 2:29 やっぱり二時間くらい? もっとかかってるかも ながら 明日は メソッド戻り型のthis型 まで やっぱ26項目にしようか ◎クラスの継承まで でかそう まぁ速度重視、ってことで あと103こうもくなので 4日でおわり つまり やはり 2/21(月)におわる その次の日にこれをブログにしたい
wwwwwwww
2022/02/18 23:25
分割代入引数から https://typescriptbook.jp/reference/functions/destructuring-assignment-parameters > JavaScriptでは分割代入構文は関数の引数でも使えます。 > function foo({ a, b }) { > foo({ a: 1, b: 2, c: 3 }); プロパティをそのまんま入れられる感じっぽい > function foo({ a: x, b: y }) { > 配列の分割代入引数は、カギカッコの中に配列要素を代入する変数名を書きます > function bar([a, b]) { > bar([1, 2, 3]); > function foo({ a, b }: { a: number; b: number }) {} > function bar([num1]: number[]) {} > function bar([num1, num2]: [number, number]) {} 2つ指定するのがタプル型 多分 JavaScriptでは、分割代入引数に対応するオブジェクトプロパティや配列要素が無い場合、undefinedが代入されます。一方、TypeScriptでは分割代入引数に対応するオブジェクトプロパティや配列要素が無いと、コンパイルエラーになります。 {} や [] がひきすうになるのが分割代入引数 function foo({ a = 0 }) { function foo({ a = 0 }: { a?: number | string }) {} ?がいるデフォルト引数には プロパティの既定値からプロパティの型が予想できる場合、型注釈を省略できる場合もあります。 function foo({ a, b } = { a: 0, b: 0 }) { 引数全体が無い、または、undefinedの場合に採用されます。 bar([1]); 1 undefined function foo({ a }: { a?: number } = { a: 0 }) {} > JavaScriptでは、分割代入引数の引数名と同じ変数が定義済みであれば、オブジェクトリテラルのプロパティ名を省略し、変数だけ渡すことができます。 よくみる > bmi({ weight, height }); 長い項目多い かんすうのコーナーの中 > JavaScriptやTypeScriptの関数には、Pythonにあるキーワード引数のような機能はありません。その代わり、分割代入引数を応用することで、キーワード引数と同じようなことができます。 python func(x=1, y=2, z=3) # => 1 2 3 べんり キーワード引数と同じような機能はRubyや、Scalaの名前付き引数(named argument)などに見られます Ruby にあるんだ Options Objectパターンというデザインパターン > Options Objectパターンは複数の位置引数を受け取る代わりに、ひとつのオブジェクトを引数に受け取るように設計された関数を言います。 よくみる func({ x: 1, y: 2, z: 3 }); さらに、Options Objectパターンでは分割代入引数を応用すると、引数の部分をよりシンプルに書けるようになります。 function func({ x, y, z }) { function func({ x, y, z }: { x: number; y: number; z: number }) { でも呼び出し側が長くなるね findUsers({ country: "JP", city: "Tokyo", order: "id", sort: "asc" }); 関数宣言側をfunction func({ hoge })に変更する代わりにfunction func({ hoge: fuga })のようにします。 > function func({ x, y = 0, z = 0 }: { x: number; y?: number; z?: number }) { オプショナルなので? > function func({ x = 0, y = 0, z = 0 }: Options = {}) { 0を入れられてすごい > function isDuck(animal: Animal): animal is Duck { なんか便利そう アサーション関数 > こちらは例外を投げるかどうかで判定します > throw new Error("YOU ARE A FROG!!!"); オーバーロード > TypeScriptもこの機能を用意しているのですが、大元がJavaScriptであることが災いし、やや使いづらいです。 あと20項目 いまSwpw*オーバーロード > type Distance = { (p: Point): number; (p1: Point, p2: Point): number; (x: number, y: number): number; (x1: number, y1: number, x2: number, y2: number): number; }; 複数の定義ができる > rejectをするには例外を投げる 中級者でよんだ >awaitはasync関数の中でしか使えないこと > トップレベルawaitは触れなくていい 中級者にかいてあった感 いま paa 2022/02/19 0:25 あと15項目 ここで注目するべきはrequest1()関数の戻り値をPromiseと型指定をしている箇所です。 TypeScriptでPromiseの型を指定する場合はPromise と書きます。TにはPromiseが解決(resolve)された時に渡す値の任意の型を指定します。 async /awaitが存在します。 この構文を利用することで、非同期処理をより同期処理と同じような文脈で書くことができるようになります。 > 関数の前にasyncキーワードをつけることで、その関数は非Promiseの値を返す時にその値を解決したPromiseを返すようになります。Promiseをそのまま返すことも可能です。二重にPromiseがラップされることはありません。 なるほど > TypeScriptでは、クラスを定義するとクラス名と同じ名前の型が同時に定義されます。 あよ12項目 2022/02/19 0:45 constructor構文 フィールドは宣言時に型を省略した場合でもコンストラクタで値が代入される場合は、代入する値で型が推論されます あと10高銀 2022/02/19 0:53 > TypeScriptでは、初期化子(initializer)を使うとインスタンスのフィールドの初期値を指定できます。 便利 2022/02/19 0:56 初期化子で値の型が自明な場合、TypeScriptコンパイラーはフィールドの型を推論してくれます。そのため、初期化子を伴うフィールドは型注釈を省略できます。 TypeScriptにはJava風のアクセス修飾子があります。 nameプロパティはpublic宣言されているため、インスタンスされた変数(gorilla)からの読み書きが可能になっています privateメソッドの多くの使い方としては、自身のクラス内の長いコードを機能別に分ける時に利用します。 メソッドの引数にはアクセス修飾子を設定することはできませんがコンストラクタは特別です。 public 自身のクラス内、継承クラス、インスタンス化されたクラスのどれからでもアクセス可能 読み取り専用フィールドは、コンストラクタかフィールド初期化子でのみ値を代入できます。 クラスはオブジェクト 一方、TypeScriptでは型安全のためにこうした動的な拡張ができないようになっています。 あと4項目 2022/02/19 1:09 TypeScriptでは、Java風の静的フィールドの書き方ができるようになっています。TypeScriptで静的フィールドを宣言するにはstaticキーワードを用います。 static field: number = 123; static field = 123; TSってJSをだいぶJavaふうにしてるんだね private static field: number; static readonly field: number; readonly static メソッドなどはない fluent interfaceとは「流れるようなインターフェース」という意味で、method chaining(メソッドの連鎖)という小技を使って、可読性の高いコードを実現するメソッドの作り方のことです。 protected value: number; に入ったものが勝手にかえるというか this が this.value と評価される感じ return thisでチェインできる > public subtract(value: number): this { とすると継承しても安心 > サブクラスにコンストラクタを書く場合、スーパークラスのコンストラクタは必ず呼び出す必要があります。スーパークラスのコンストラクタはsuper()で呼び出します。 中級者でみた 2022/02/19 1:19 よみおわ https://typescriptbook.jp/reference/object-oriented/class/class-inheritance 2022/02/20 1:58 今日は Readonly まで > TypeScriptでは、クラスに1つでも非パブリックなプロパティがあると、そのクラスだけ構造的部分型ではなく公称型(nominal typing)になります。 なるほど > TypeScriptにはabstract修飾子があり抽象クラスを表現できます。 抽象クラスとは直接インスタンス化(new)することができず、必ずスーパークラスとして利用することを保証するものです > 抽象クラス内のメソッドにもabstract宣言を行うことができます。interfaceと同じようにサブクラスは抽象メソッドを実装する必要があります。 final sealed ない (継承付加にさせる) もう4つ終わった 2022/02/20 2:05 JavaやPHPなどの言語では、インターフェースが定義できますが、JavaScriptにはそれに相当する構文がありません。一方、TypeScriptにはインターフェースがあります。 interface SomeInterface { なるほど便利 だけどJSとはどんどんべつにナッテくね interface/ ができそう TypeScriptではメソッドだけでなく、パブリックフィールドも定義できます。 TypeScriptは構造的部分型なので、インターフェースと実装関係がないオブジェクトの型注釈としても利用できます。 const taro: Person = { 組み込みapiで 13 class Developer implements Human { class TypeScriptProgrammer implements Human, Programmer { TypeScriptでは、extendsキーワードを利用して定義済みのインターフェースを継承して、新たにインターフェースを定義することができます。 プロパティを部分型に宣言しなおす ある型からその型のリテラル型にすることも、ユニオン型から部分的に選択することもTypeScriptではそれぞれサブタイプにしていることと同じ意味があります サブクラスにすることもできます。 interface IndexPage extends WebPage { path: "/"; ES2016.array.ts > type Array = ES2016Array & ES2019Array ; インターフェイス判定をするには型ガードを自前で実装する必要があります。以下はその例のisStudent()です。 インターフェースは型の宣言であり、型エイリアスは型に名前をつける機能です。この定義に立ち返って使い分けをしましょう。 ジェネリクスもないJavaScript はんぶくくきた 2022/02/20 2:40 つかれるまでやろうか MapはJavaScriptの組み込みAPIのひとつで、キーと値のペアを取り扱うためのオブジェクトです。Mapにはひとつのキーについてはひとつの値のみを格納できます。 const map = new Map (); 長い https://typescriptbook.jp/reference/builtin-api/map 5900地 コンストラクタにキーと値の[タプル型][K, V]の配列[K, V][]を渡すとMap オブジェクトが作られます。 Mapの型変数を省略した場合、TypeScriptはコンストラクタ引数からMap の型を推論します。 コンストラクタ引数を省略した場合、空のMapが作られます。 function doSomething(map: Map ) {} めちゃ使いそう そのため、Mapはnullとundefinedを異なるキーとみなします。 NaN同士は厳密等価ではありませんが、例外的に同じキーとみなされます。 等価と厳密等価がある オブジェクトは等価でも厳密等価でもないため、別のキーとみなされます。 たまに使いそう Mapにキーと値のペアを追加するにはsetメソッドを使います。 map.set("a", 1); getメソッドは、キーが存在しない場合、undefinedを返します。 deleteの戻り値は、キーが存在した場合true、そうでない場合falseになります。 > この場合、getで値を取得して、その値がundefinedでないことをチェックするとうまくいきます。 Mapに登録されている要素をすべて削除するにはclearメソッドを使います。 keysメソッドはキーの反復可能オブジェクトを返します。 valuesメソッドは値の反復可能オブジェクトを返します。 entriesメソッドはキーと値の反復可能オブジェクトを返します。 よくみる > for (const [key, value] of map) { とうろくされたzilyunn const map2 = new Map(map1); シャローコピー MapをJSON化する場合は、一度オブジェクトにする必要があります。 const keyValues = [...map]; [["a", 1], ["b", 2], ["c", 3]] > const map = new Map(Object.entries(obj)); オブジェクトがMapになる const obj = Object.fromEntries(map); この Map がおわったらあと12こう木 今日は 反復の順序が複座つなオブジェクト メソッドで操作するMap、 言語仕様だから専用の書き方があるオブジェクト Mapは組み込みapi 一旦…最後までか? Errorまでか? 2022/02/20 3:01 Setもそこそこでかい https://typescriptbook.jp/reference/builtin-api/set 2500地 Setには重複する値が格納できません。Setに格納された値は一意(unique)になります。 コンストラクタに配列を渡すと、値がSetに格納されます。 空のSetオブジェクトのTypeScript上の型はSet になります。これでは後からSetに値を追加できないので、空のSetを作るときは、Setの型変数を指定する必要があります。 const fruits = new Set (); Mapのキーな指板 Set JSONにするとき const array = [...fruits]; console.log(JSON.stringify(array)); 「Setに渡した値は重複しない」という特性を使って、配列から値が重複する要素を取り除く処理に応用できます。 const array2 = [...new Set(array1)]; あと11項目 2022/02/20 3:04 TODO: 実務ではdate-fnsの使用を推奨する ErrorはJavaScriptの組み込みAPIのひとつで例外を取り扱うためのオブジェクトです。 JavaScriptにもある 組み込みAPIとしてErrorには次のサブクラスがあります。 EvalError InternalError RangeError ReferenceError SyntaxError TypeError URIError 便利そう class CustomeError extends Error { わかる console.log(err.stack); name と message を一気にだせて便利な .stack もし捕捉した値があるクラスのインスタンスまたはある型であるかを判定したい場合はinstanceof, keyofあるいは型ガードを使います。 if (e instanceof Error) { モジュールは、importまたはexportを1つ以上含むJavaScriptファイルを言います。 ナウくて、前ははっきりと知らなかった部分 importなど export require めちゃなが 9000じ https://typescriptbook.jp/reference/import-export-require 2022/02/20 3:37 export const foo = "foo"; JavaScriptのモジュールは、明示的にexportをつけた値だけが公開され、他のモジュールから参照できます Javaなどの他の言語では、モジュール(パッケージ)のメンバーがデフォルトで公開になり、非公開にしたいものにはprivate修飾子をつける言語があります。そういった言語と比べると、JavaScriptは基本方針が真逆なので注意が必要です。 モジュールのコードが評価されるのは、1回目のimportのときだけです。2回目以降のimportでは、最初に評価した内容が使われます。言い換えると、モジュールは初回importでキャッシュされるとも言えますし、モジュールはいわゆるシングルトン(singleton)的なものとも言えます。 もしjQueryに依存するパッケージがあるとすれば、jQueryの宣言より下に書く必要があります。 パッケージが少なければまだしも、増えてくると依存関係が複雑になります。もしも読み込む順番を間違えるとそのhtmlでは動作しなくなるでしょう。 require() Node.jsでは現在でも主流の他の.jsファイル(TypeScriptでは.tsも)を読み込む機能です。基本は次の構文です。 const package1 = require("package1"); このとき.js, .jsonとTypeScriptなら加えて.tsを省略することができます。TypeScriptでの開発においては最終的にJavaScriptにコンパイルされることを考慮すると書かないほうが無難です。 .jsを.tsと同じ場所に出力するようにしているとTypeScriptにとって同じ名前の読み込ことができるファイルがふたつ存在することになります。このときTypeScriptは.jsを優先して読み込むので注意してください。 また指定したパスがディレクトリで、その中にindex.js(index.ts)があれば、ディレクトリの名前まで書けばindex.js(index.ts)を読み込んでくれます。 他のファイルを読む込むためにはそのファイルは何かを出力している必要があります。そのために使うのがこの構文です。 module.exports = (i) => i + 1; const increment = require("./increment"); このmodule.exportsはひとつのファイルでいくらでも書くことができますが、適用されるのは最後のもののみです。 exports.increment = (i) => i + 1; const util = require("./util"); console.log(util.increment(3)); const { increment } = require("./util"); console.log(increment(3)); const { increment: inc } = require("./util"); ES6で追加された機能のため、あまりにも古いブラウザでは動作しません。 require()はファイル内のどこにでも書くことができる一方でimportは必ずファイルの一番上に書く必要があります。 import * as package1 from "package1"; import package2 from "package2"; 微妙に違う export default (i) => i + 1; node.js の require に default 的なやつと 名前付きのやつがあったので、 ES Moduleでも二通りアルンだね まぁ、突っかかったときとかは https://typescriptbook.jp/reference/import-export-require を読み返そう 2022/02/20 3:54 > ES Moduleではimportをファイルの先頭に書く必要があります。これは動的に読み込むファイルを切り替えられないことを意味します。このimport()はその代替手段にあたります。 require()と異なる点としてはimport()はモジュールの読み込みを非同期で行います。つまりPromiseを返します。 import("./util").then(({ increment }) => { console.log(increment(3)); // @log: 4 }); なるほど > Node.jsでES Moduleを使う > ES Moduleとして動作させたいJavaScriptのファイルをすべて.mjsの拡張子に変更します。 ややこしい importで使うファイルの拡張子が省略できないことに注意してください。 > "type": "module" package.jsonにこの記述を追加するとパッケージ全体がES Moduleをサポートします。 なお"type": "module"の省略時は"type": "commonjs"と指定されたとみなされます。これは今までとおりのNode.jsです。 CommonJSで書かれたJavaScriptを読み込みたくなったときはCommonJSで書かれているファイルをすべて.cjsに変更する必要があります。 ES Moduleにはrequire()がなく、一手間加えて作り出す必要があります。 import { createRequire } from "module"; すべてをES Moduleとして読み込むこの設定は、多くのパッケージがまだ"type": "module"に対応していない現状としては非常に使いづらいです。 TypeScriptでは一般的にES Module方式に則った記法で書きます。 執筆時(2021/01) ブラウザ用であればES Moduleを、サーバー用であればCommonJSが無難な選択肢になります。 ひとつのファイルから複数exportできる namedがつよそう ロジックが変わったこととそれによる修正を強制したいのであればnamed exportを使う方がわかりやすく、そしてエディター、IDEを通して見つけやすくなる利点があります。逆に、公開するパッケージのようにAPIが一貫して明瞭ならばdefault exportも価値があります。 2022/02/20 4:08 シングルプロセス 3700地 https://typescriptbook.jp/reference/single-process-and-callback 02:00 にはじめてる あと7項目 ブロッキングの逆の概念です。Node.jsはノンブロッキングI/Oを取り扱うことができます。 いままでsetTimeout()は第2引数のミリ秒だけ遅延させてコールバック関数を実行すると説明していましたが、厳密にはミリ秒経過後にメッセージキューに戻すだけで、そのコールバック関数が即座に実行されるわけではありません。 終わった 2022/02/20 4:17 9分 ながら つまり、 400地/分かな つまり、1時間 24000地、 2時間で 50000地 一日に文庫本 100ページ読んでることになる TypeScriptでは型から別の型を導き出す機能があります。既存の型を再度利用して、新たな型を生み出すことを本書では「型の再利用」と呼ぶことにします。 型の再利用とは、変数の再利用のメタファーなのです。 あとご項目 2022/02/20 4:21 TSって 方追加ダケタなくて、インターフェイスとか色々も追加されてるのね TypeScriptのtypeofは変数から型を抽出する型演算子です。 type Point = typeof point; ここで説明したのはTypeScriptのtypeof型演算子です。JavaScriptのtypeof演算子と同じ名前ですが、まったく別のものなので注意してください。 めちゃむず べつの名前にすればいいのに type PersonKey = keyof Person; type BookKey = "title" | "price" | "rating"; interfaceとtypeの違い の次が tsconfigの設定項目に関して なので、この辺飛ばしてそうかも?? > インデックス型にkeyofを用いると、インデックスキーの型が返ります。 キーがstringのインデックス型は、stringではなくstring | numberが返ります。number型のキーアクセスのobj[0]はobj["0"]と同じになるからです。 any型にkeyofを使うとstring | number | symbol型が返ります。 このメモも 42400文字ある既に 2022/02/20 4:25 keyofを使うとそもそも書き写す必要がないため、便利な上に安全なコーディングができます。 ユーティリティ型(utility type)は、型から別の型を導き出してくれる型です functionが実行時の世界の関数だとしたら、ユーティリティ型は型の世界の関数といったイメージです。 Required は、Tのすべてのプロパティからオプショナルであることを意味する?を取り除くユーティリティ型です。 type RequiredPerson = Required ; Readonlyの効果は再帰的ではない やっとおわり 2022/02/20 4:28 2時間はん ながら 明日は noUnusedParameters まで 確かにあと2日でおわりそう
2022/02/20 19:31
開始 Partialは、オブジェクト型Tのすべてのプロパティをオプションプロパティにするユーティリティ型です。 PartialをOptions Objectパターンに応用すると、省略可能でありながら見やすい関数を実装できます。 急にながくなった Partial を使って見た目をよくできます。 }: FindUsersArgs): Promise { }: FindUsersArgs = {}): Promise { > Record はプロパティのキーがKeysであり、プロパティの値がTypeであるオブジェクト型を作るユーティリティ型です。 オブジェクト型 type Person = Record<"firstName" | "middleName" | "lastName", string>; Pick は、型TからKeysに指定したキーだけを含むオブジェクト型を返すユーティリティ型です。 便利そう 型引数Tにはオブジェクト型を代入します。 type Person = Pick ; このようにすればBookInputDataは少なくともBookとコード上の繋がりができる上に、authorプロパティの型変更を自動で追従してくれるようになります。 Omit は、オブジェクト型TからKeysで指定したプロパティを除いたオブジェクト型を返すユーティリティ型です。 Omit のKeysにTには無いプロパティキーを指定しても、TypeScriptコンパイラーは指摘しません。たとえば、Keysにタイポがあっても検出できないので注意が必要です。 Extractは2つのユニオン型の共通部分を導き出すことにも使えます。 次は Mapped type https://typescriptbook.jp/reference/type-reuse/mapped-types あと20項目 2022/02/20 19:59 入力の形式が決まっているのであればMapped typeの使用を検討できます。 べんりそう type SystemSupportLanguage = "en" | "fr" | "it" | "es"; type Butterfly = { [key in SystemSupportLanguage]: string; TypeScriptのインデックスアクセス型(indexed access type)は、プロパティの型や配列要素の型を参照する方法を提供します。 type A = { foo: number }; type Foo = A["foo"]; keyof型演算子と組み合わせると、オブジェクトの全プロパティの型がユニオン型で得られます。 > 配列型の要素の型を参照するのにもインデックスアクセス型が使えます。要素の型を参照するには、配列型に[number]をつけます。 めちゃむず type StringArray = string[]; type T = StringArray[number]; type State = typeof stateList[number]; type State = "open" | "closed" type Tuple = [string, number]; type T = Tuple[0]; 型の安全性とコードの共通化の両立は難しいものです。 型の安全性を重視しようとすると、同じようなコードを量産する必要が出てコードの共通化が達成しづらくなります。 ジェネリクスの発想は実はとてもシンプルで、「型も変数のように扱えるようにする」 function chooseRandomly (v1: T, v2: T): T { chooseRandomly ("勝ち", "負け"); chooseRandomlyの は型変数名の定義です。慣習としてTがよく使われますが、AでもTypeでも構いません。関数の引数の型や戻り値の型として書かれたTは型変数を参照しています。 Arrayは特別に別の記法で型表記をすることもできます。これらについては配列のページに詳細がありますので併せて参照ください。 ジェネリクスの型定義はひとつである必要はなく、複数の型定義を持つことも可能です。 型変数(type variables)は、もうひとつの便利な入れ物です。ただし、入れられるのは「値」ではなく「型」という違いがあります。 この関数を利用するコードは、numberなどTに好きな型を代入することができます: const value = printAndReturn (123); TypeScriptでは、型引数にも型推論が行われます。型引数推論(type argument inference)と言われます 変数の123から型変数Tの型はnumber型になることがコンパイラからは推測可能なので、次のコードのように型引数の記述を省略することもできます。 const value = printAndReturn(123); function func5<かた>(x: かた) {} 型変数名に使えないものは数字ではじまるもの、classなどの予約語です。 単純なジェネリクスで、型変数が2つある場合は、TとUが用いられることがあり、その理由はアルファベット順でTの次がUだからです。この規則にしたがって、3つ目の型変数はVする場合もあります。 複数の型変数がある場合、型変数に意味のある名前をつけることもあります。その場合、TKey、TValueのようにT接頭辞を付けた命名規則がしばしば使われます。ただし、これは「型変数名にはTを用いる」という慣習ほどは一般的でないように思われます。 型変数名を単語にする場合は、大文字始まりのキャメルケースにすることが普通です。 ジェネリクスはそもそも抽象的なものごとを扱うため、具体的な名前が付けられないため、意味を持たないTのほうがいいという考え方があります。 Elementのような型変数名を定義すると、一見するとそれがクラス名のように見えてしまいます。混乱を避けるためにもTのほうがよいという意見があります。 型変数にも同じことが言えて、型変数のスコープが広いものは単語にし、短いジェネリック関数の中でしか使わない型変数は1文字が妥当という考え方があります。 コンパイラは存在しないプロパティへの参照が発生する可能性を検知してコンパイルエラーとしているのです。 function changeBackgroundColor (element: T) { このextendsキーワードはインターフェースに対しても使います。インターフェースは実装のときはimplementsキーワードを使いますが型引数に使うときはimplementsを使わず同様にextendsを使います。 type MyErrorEvent = { type MyErrorEvent = { class Aubergine { デフォルト型引数は左から順に参照されるため、左にあるジェネリクスが右のジェネリクスを指定することはできません。 2022/02/20 21:20 tsconfig.jsonを設定する に到達 https://typescriptbook.jp/reference/tsconfig/tsconfig.json-settings 4400もじ あと12項目 Node.jsはそれ自身ではTypeScriptをサポートしているわけではないため、TypeScriptの導入をする時はTypeScriptの設定ファイルであるtsconfig.jsonが必要です。 typescriptがグローバルインストールされていればnpx不要 使いたいtargetには使いたい機能がない、でも使いたい。そのような時はlibオプションを指定することで使うことができるようになります。 むずかめんどそうポイント 指定したtargetでは実装されていないライブラリや、必要がないライブラリを除外したいときに使います。 軽くなりそう > "target": "es2018", > "lib": [ "es2018", "esnext.AsyncIterable", "esnext.Array", "esnext.Intl", "esnext.Symbol" ] あえて古いコードで動かしている、または古いNode.jsを使っているといった事情がなければ最新に近い物を指定することは問題ありません。 Node.js 14.xであれば"target": "es2020"は無難な選択肢です。 またBabelなどの専用のコンパイラやモジュールバンドラに処理を任せたい場合はtargetに"esnext"を指定して、そこからバージョンに合わせたコンパイルを各々にお願いすることになります。 Node.jsのバージョンごとにサポートされているEcmaScriptの機能は node.green で確認することができます。 とくにnpm installしたものであればこれらをパッケージと呼びます。 モジュール読み込みの仕組みが異なっているライブラリの互換性は一般的にはないものと考えてください。そしてこれはフロントエンドとバックエンドでは異なります。 es2015, es2020, esnext 通称esmoduleと呼ばれるモジュール読み込みの解決方法です。 スクラッチから作るということは現在の資産との整合性の都合、しがらみが一切ない状態です。ここから作るならこれだけは満たしておけば型に満ちたプログラミングができるという紹介です。 strictはstrict系のコンパイラオプションを一括で有効化するコンパイラオプションです。 個々の設定が優先されます。 戻り値の型注釈を必須にしたい場合は、noImplicitReturnsを有効にしてください。 再開 2022/02/21 0:36 あと9項目 さすがに個々の設定は短いかな? とりあえず、できるものならtrueにするのがよさそう TypeScriptの関数には引数の双変性(parameter bivariance)という性質があります TypeScriptの関数型は、引数の反変性と引数の共変性の両特性を持っています。この両特性は一言で、引数の双変性と言います。 引数の共変性を許さないstrictFunctionTypes strictFunctionTypesのチェックが働くのは関数型だけです。メソッド型には働きません。 プロパティがオプションの場合も警告が出ません。 まぁ、すいしょうなのは極力trueにするよね 2022/02/21 0:48 あと4つ alwaysStrict 'use strict'を各ファイルの先頭に付加します。 便利 終わり 2022/02/21 1:05 機能ほど、長い項目なくて楽だった 明日は25項目で最後まで。
2022/02/21 22:57
やってこ https://typescriptbook.jp/reference/tsconfig/exactoptionalpropertytypes から 型定義ファイルを同梱することにより補完やコードチェックとして利用することができます。 ヘッダーファイルだ tsc -d でつくれる JavaScriptで書かれたパッケージだが、 DefinitelyTypedに登録されている TypeSearchからパッケージ名を検索しインストールを行います npm install @types/express --save-dev # 型定義ファイルのインストール なるほど @types/ の意味がやっとわかったぞ 型定義ファイルを一緒に出力しましょう。そのためにはtsconfig.jsonにあるdeclarationの項目をtrueに変更します。 "sourceMap": true, > 確かにフロントエンドを動的にしたいのであればほぼ避けて通れないJavaScriptと、バックエンドでも使えるようになったJavaScriptで同じコードを使いまわせれば保守の観点でも異なる言語を触る必要がなくなり、統一言語としての価値が大いにあります。 むふう "extends": "./tsconfig.base.json", このようなtsconfig.xxx.jsonができていれば、あとは次のようにファイル指定してコンパイルをするだけです。 tsc -p tsconfig.cjs.json module bundlerは容量削減のための涙ぐましい努力を続けています Tree Shakingとは使われていない関数、クラスを最終的なjsファイルに含めない機能のことです ここで言及している副作用とは以下が挙げられます。 exportするだけで効果がある プロトタイプ汚染のような、既存のものに対して影響を及ぼす "sideEffects": ["./xxx.js", "./yyy.js"], Generatorを使用した関数はアロー関数での表記ではなく、必ずfunction*() {}と書く必要があります。次は可能なGeneratorの記述方法です。 中級者でみた 現在でも大量のデータを取得したいときに一度ではなく、小出しに取得したいときにGeneratorは使い道があります。 プロパティへのインターセプター(参照・代入・監視などの意味)としGetter/Setterがあります。 あと 12項目 2022/02/21 23:56 自分たちでこのパッケージに手を加えることは容易ではないため (できなくはありません) 。制作者にプルリクエストを出してバグフィックスが行われるまで開発を止めるというのも現実的ではありません 浅いコピーの実装は昨今のJSでは大変楽になっており、次のコードで完成です。 const shallowCopied: object = { ...sample }; スプレッド構文は配列をはじめとするコレクションに対しても使うことができます。 const merged = { ...obj1, ...obj2 }; const merged = { ...obj1, ...obj2, ...obj3, // ... }; あと10項目 2022/02/22 0:08 2つ目の方法はlodashを用いるものです。lodashはさまざまな便利関数を提供するライブラリで、その中のひとつにpickというオブジェクトのサブセットを得るための関数があります。 npm install -D @types/lodash 型情報もゲットしよう 関数やメソッドでオブジェクトひとつを引数として受け、戻り値もオブジェクトひとつとする RORO という考え方があります。RORO は Receive an Object, Return an Object の略です。この考えは JavaScript ならびに TypeScript では大きな恩恵をもたらします。 TypeScriptでは値と型に同名を与えてその両方を区別なく使うことができるテクニックがあります。これをコンパニオンオブジェクトと呼びます。 これは、クラスを作るほどでもなけどそれっぽいファクトリーメソッドとオブジェクトが欲しいときに重宝します。 type Account = typeof account; > } as const; type Account = typeof account; リテラル型になる > plan: "Standard" as "Free" | "Standard" | "Premium", この const の 型への変換べんりだな typeof keyofはオブジェクトの型に使うとそのオブジェクトのキーをユニオン型にして返します。上記のTypeOfLanguage型があれば type Language = keyof TypeOfLanguage; type Language = keyof typeof conf; keyofは値ではなく (オブジェクトの) 型に対して使用できる type ConfirmationMessage = typeof conf[Language]; type Currency = typeof currencies[number]; numberをいれると 0とか 1とかの代わりのユニオン型になるらしい () 即時実行関数の一部 (IIFE: immediately invoked function expression) js 定義されるとすぐ実行される即時実行関数式(IIFE; Immediately Invoked Function Expression)の一部に用いられる書き方です。 - 修飾子の削除 ts readonlyや?などの修飾子を削除します。 type MyRequired= { [k in keyof T]-?: T[k]; }; type Writable = { -readonly [k in keyof T]: T[k]; /** JSDoc 慣習的にJSDocなどのドキュメンテーションコメントの開始を表す記号です。これはJavaScriptやTypeScriptの構文ではなく、複数行コメントを用いたドキュメンテーションに慣習的に用いられるものです。 >> ビット右シフト演算子 (right shift) js 左の値のビットを右の値の数だけ右にずらします。 const a = 8; 00001000 const b = 3; console.log(a >> b); 00000001 ?? Null合体 (nullish coalescing operator) js 左の値がnullまたはundefinedのときに右の値を返します。そうでない場合は左の値を返します。 console.log(undefined ?? 1); 1 console.log(2 ?? 1); 2 const user2 = { name: "kaori" }; user2.name ??= "taro"; console.log(user2.name); kaori https://typescriptbook.jp/symbols-and-keywords @ デコレーター (decorator) ts デコレーターはクラスやクラスメンバーに注釈を追加するもので、デコレーターを使うのに用いられる記号です。 そいうのもあるのね 2022/02/22 0:46 もうすぐで二時間かな? インデックス型(index signature)の開始に用いられる記号です。 type StringKeysAndStringValues = { [key: string]: string; }; また、慣習的に使わない変数の受け取り先に使われることがあります。たとえば、2つの引数を受け取るコールバック関数で、第2引数だけを使う場合、第1引数をアンダースコアにする書き方をするコードが中にはあります。 [1, 2, 3].map((_, index) => { // _ は 1, 2, 3のような要素値。それを使わないという意味で _ にしている if文やfor文などの構文を伴わないブロック文は、単に変数のスコープを分けることを目的にしていることがあります。 { const value = 1; } ~~ Double Tilde js ビット否定演算子を2つ重ねたもので、小数点以下を消し去る計算をするイディオムです。JavaScriptにこういう演算子があるわけではなく慣習的なものです。double tildeの計算結果は、正の数についてはMath.floorと同じに、負の数はMath.ceilと同じになります。 typeof typeof演算子 (typeof) js 与えられた値の型を表す文字列を返します。 console.log(typeof 123); "number" typeof typeof型演算子 (typeof) ts 変数から型を抽出する演算子です。 なぜ「これはTSの方のtypeof」とか見分けられるのか JSのは変数に使えないのかな? void void演算子 (void) js 戻り値をundefinedにします。 console.log(void 123); TypeScript Playground https://www.typescriptlang.org/play エディターのコードを文字列圧縮ライブラリで圧縮して文字列をURLに設定する URLを共有する 共有されたURLが開かれる時に圧縮された文字列をデコードしてエディターに展開する こんなにちっちゃく圧縮できるんだね おわった! 2022/02/22 0:54