経緯
- 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