Web開発ログ | エンジニアに役立つ情報 | 開発の中での気づきを発信

高卒Devlog

TSLab【第9回 TypeScript勉強会】Classes & Modules

thumbnail

こんにちは! RYOTAです!

当記事をご覧くださりありがとうございます!

当記事はTSLab勉強会(定例会)のレポート記事になります!

はじめに

私が運営しているTSLabの第9回TypeScript勉強会の実施ログとなります。
今回のテーマは「Classes」と「Modules」です!

ディスカッション内容

今回の参加者は少人数かつTypeScriptを実務で使っている方々だったので、ディスカッション内容と言いつつ、簡単な感想の共有をしながらサクッと流し気味に確認した回となりました。

Classes

Getters / Setters

クラス内で get 〇〇 で記述した箇所がgetterとして定義され、set 〇〇 で定義した箇所がsetterとして定義されます。
下記のソースの場合、_hogeはプライベートのためクラス外からのアクセスが出来ませんが、getterを介すことで値の取得が可能です。
アクセス出来ないということは値の変更を変えることが出来ないのですが、この場合はsetterを介すことで値の変更が可能となります。

class Test {
  // プライベートに設定
  private _hoge = 0;

  // getter
  get hoge() {
    return this._hoge;
  }

  // setter
  set hoge(value) {
    this._hoge = value;
  }
}

// Testのインスタンスを生成
const test = new Test()

console.log(test._hoge)
// エラー -> Property '_hoge' is private and only accessible within class 'Test'.
console.log(test.hoge)
// -> 0
test.hoge = 5
console.log(test.hoge)
//  -> 5

実務で使った記憶があまりない...(あるとしてもVuex内でくらい...?)

implements

interfaceで定義した型をclassに割り当てる場合、implements句を使用することで可能となります。
下記のソースの場合、TestType型にはhogeというプロパティが存在しますが、TestTypeを割り当ててるTest2クラスにはhogeプロパティが存在しないのでエラーを返しています。

interface TestType {
  hoge(): void;
}

class Test implements TestType {
  hoge() {
    console.log("hoge");
  }
}

// エラー -> Class 'Test2' incorrectly implements interface 'TestType'. Property 'hoge' is missing in type 'Test2' but required in type 'TestType'.
class Test2 implements TestType {
  fuga() {
    console.log("fuga");
  }
}

クラスの初期化順序

クラス継承を行なう場合、下記の順序を意識しないと意図しない挙動となるので注意が必要。

  1. 基本クラスフィールドが初期化
  2. 基本クラスのコンストラクターを実行
  3. 派生クラスフィールドが初期化
  4. 派生クラスコンストラクターを実行

Cross-hierarchy protected access

公式ドキュメントのCross-hierarchy protected accessというパートについて、深めの議論を行いましたが結論よくわからず。笑
Documentation - Classes How classes work in TypeScript
(スーパークラスでprotectedになってるプロパティはサブクラスでアクセス出来ない...ってこと...?)
そもそも何を指しているのかすら分からないので、
この箇所について分かる方は是非教えてください...🙇‍♂️

Modules

このパートはTypeScriptを使ってる人であれば当然知っている内容だったのでサラッと流しました。
この辺り押さえておけば良さげでしょうね。

export default Hoge
import Hoge from './hoge.ts'

export Hoge
import {Hoge} from './hoge.ts'

import * as Hoge from "./hoge.js"

import "./hoge.js"

ちなみに、import の後にtypeを付与すると型情報だけインポート出来るらしいです。(知らんかった!!!)

import type { HogeType, FugaType } from "./hoge.js"

モジュールと型を一気にインポートするとグチャッとする時があるので、typeで型だけインポートして分けた方がスッキリ書けそうですね!良き!

import + require

公式に載っていた下記のソースですが、import句とrequire句を合わせて使っていてん?となりました。
時間の問題でスルーしたのですが、これって何か意味あるんでしょうかね?
これも分かる方は教えてください🙇‍♂️

import fs = require("fs");

https://www.typescriptlang.org/docs/handbook/2/modules.html#es-module-syntax-with-commonjs-behavior

さいごに

今回は「Classes」と「Modules」を一気に進めてきました。
classはバックエンドでは良く使うのですが、フロントだとあまり使わないので軽く触る程度で留めました。
私はExpressをclassベースで書いていたのですが、他の方はclassを用いずに書いているようだったので、尚更使わないかもしれませんね。笑
今回まででTypeScriptの基礎は完了したので、次回以降はより突っ込んだ内容に踏み込んでいこうと思います!
最後までご覧いただきありがとうございます!
一緒にTypeScriptを学びたい方はぜひ下記のアカウントからご連絡ください!