LoginSignup
0
1

More than 1 year has passed since last update.

TypeScriptのClassまとめ

Posted at

Classの定義

class.ts
class Person {
    name: string;
    constructor(initName: string) {
        this.name = initName;
    }
}
const quill =  new Person('Quill');
console.log(quill);
出力結果
$ node dist/class.js
Person { name: 'Quill' }

コンパイルされるjsファイルを確認(es6)
jsではクラスにプロパティを定義するフィールドはない。

class.js(es6)
"use strict";
class Person {
    constructor(initName) {
        this.name = initName;
    }
}
const quill = new Person('Quill');
console.log(quill);

es5でコンパイルするとクラスの記述がなくなり、代わりにコンストラクタ関数で定義されている。
【JS入門】コンストラクタ関数について

class.js(es5)
"use strict";
var Person = /** @class */ (function () {
    function Person(initName) {
        this.name = initName;
    }
    return Person;
}());
var quill = new Person('Quill');
console.log(quill);

メソッドの定義

class Person {
    name: string;
    constructor(initName: string) {
        this.name = initName;
    }
    greeting() {
        console.log(`hello ${this.name}`);
    }
}

const quill =  new Person('Quill');
quill.greeting();
出力結果
hello Quill

メソッドをオブジェクトに代入して実行する場合

class Person {
    name: string;
    constructor(initName: string) {
        this.name = initName;
    }
    greeting() {
        console.log(`hello ${this.name}`);
    }
}

const quill =  new Person('Quill');
quill.greeting();

const anotherQuill = {
    anotherGreeting: quill.greeting
}
anotherQuill.anotherGreeting();
出力結果
hello Quill
hello undefined

undefinedになるのは、anotherQuilの中で定義している時点でgreeting()のthisはanotherQuilを指しているから。anotherQuilオブジェクトにはnameプロパティがない。
よって以下のようにプロパティを定義してやれば出力される。

thisは呼び出されたときに何を参照するか決まるので注意。

class Person {
    name: string;
    constructor(initName: string) {
        this.name = initName;
    }
    greeting() {
        console.log(`hello ${this.name}`);
    }
}

const quill =  new Person('Quill');
quill.greeting();

const anotherQuill = {
    name: 'anotherQuill',
    anotherGreeting: quill.greeting
}
anotherQuill.anotherGreeting();
出力結果
$ node dist/class.js
hello Quill
hello anotherQuill

メソッドを実行する前にundefinedが出力されるのを回避する方法

上記の場合、undefinedが出力されることは実行結果を確認するまでわからない。
実行前に確認するためにはメソッドの引数を以下のように定義する。

class Person {
    name: string;
    constructor(initName: string) {
        this.name = initName;
    }
    greeting(this: { name: string }) { // ここ追記
        console.log(`hello ${this.name}`);
    }
}

const quill =  new Person('Quill');
quill.greeting();

const anotherQuill = {
    anotherGreeting: quill.greeting
}
anotherQuill.anotherGreeting();

greetingを実行する場合オブジェクトのnameプロパティを参照すると明記することで、
vscode上でanotherGreeting()を実行する前にエラー表示を確認することができる。(一番下の行)
スクリーンショット 2022-04-19 14.17.06.png

クラスを型として定義する

上でgreeting()の引数としていたthisの書き方を下記のようにできる。
このようにすることでクラスを型として定義することができる。
この場合、anotherQuillにはgreeting()とnameプロパティを定義しなければならない。

class Person {
    name: string;
    constructor(initName: string) {
        this.name = initName;
    }
    greeting(this: Person) {
        console.log(`hello ${this.name}`);
    }
}

const quill =  new Person('Quill');
quill.greeting();

const anotherQuill = {
    greeting: quill.greeting,
    name: 'anotherQuill'
}
anotherQuill.greeting();

public修飾子とprivate修飾子

class Person {
    public name: string;
    private age: number;
    constructor(initName: string, initAge: number) {
        this.name = initName;
        this.age  = initAge;
    }
    greeting(this: Person) {
        console.log(`hello ${this.name}. I'm ${this.age}`);
    }
}

const quill =  new Person('Quill', 24);
quill.greeting();

何も指定しないとpublicになる。
privateにすると読み込みも書き込みもできない。

初期化の省略

constructor()に修飾子を付けて引数を定義すると省略することができる。

class Person {
    constructor(public name: string, private age: number) {
    }
    greeting(this: Person) {
        console.log(`hello ${this.name}. I'm ${this.age}`);
    }
}

const quill =  new Person('Quill', 24);
quill.greeting();

readonly

readonlyを指定するとクラス内外から書き込みすることができない。
ただしconstructorでは書き換えることができる。

class Person {
    constructor(public readonly name: string, private age: number) {
        this.name = 'readonly'
    }
    greeting(this: Person) {
        console.log(`hello ${this.name}. I'm ${this.age}`);
    }
}

継承とprotected修飾子

protectedを指定することで継承した子クラスからプロパティにアクセスできる。

class Person {
    constructor(public readonly name: string, protected age: number) {
        this.name = 'readonly'
    }
    greeting(this: Person): void {
        console.log(`hello ${this.name}. I'm ${this.age}`);
    }
}

class Teacher extends Person {
    constructor(name: string, age: number, public subject: string) {
        super(name, age);
    }
    greeting(): void {
        console.log(`hello ${this.name}. I'm ${this.age}. subject is ${this.subject}`);
    }
}

ゲッターとセッター

class Person {
    constructor(public readonly name: string, protected age: number) {
        this.name = 'readonly'
    }
    greeting(this: Person): void {
        console.log(`hello ${this.name}. I'm ${this.age}`);
    }
}

class Teacher extends Person {
    get subject() {
        if(!this._subject) {
            throw new Error("no subject");
        }
        return this._subject;
    }
    set subject(value) {
        if(!value) {
            throw new Error("no subject");
        }
        this._subject = value;
    }
    constructor(name: string, age: number, private _subject: string) {
        super(name, age);
    }
    greeting(): void {
        console.log(`hello ${this.name}. I'm ${this.age}. subject is ${this.subject}`);
    }
}

const teacher = new Teacher('Quill', 38, 'Math')
teacher.subject = 'music!!';
console.log(teacher.subject);
出力結果
$ node dist/class.js
music!!

static

class Person {
    static species = 'homo sapiens';
    static isAdult(age: number) {
        if(age > 17) return true;
        return false;
    }
    constructor(public readonly name: string, protected age: number) {
        this.name = 'readonly'
    }
    greeting(this: Person): void {
        console.log(`hello ${this.name}. I'm ${this.age}`);
    }
}
console.log(Person.species);
出力結果
$ node dist/class.js
homo sapiens

abstractクラス

abstractクラスはインスタンスを生成できない。

abstract class Person {
    static species = 'homo sapiens';
    static isAdult(age: number) {
        if(age > 17) return true;
        return false;
    }
    constructor(public readonly name: string, protected age: number) {
        this.name = 'readonly'
    }
    greeting(this: Person): void {
        console.log(`hello ${this.name}. I'm ${this.age}`);
        this.explainJob();
    }
    abstract explainJob(): void;
}

class Teacher extends Person {
    explainJob(): void {
        console.log(`I am a teacher and I teach ${this.subject}`);
    }
    get subject() {
        if(!this._subject) {
            throw new Error("no subject");
        }
        return this._subject;
    }
    set subject(value) {
        if(!value) {
            throw new Error("no subject");
        }
        this._subject = value;
    }
    constructor(name: string, age: number, private _subject: string) {
        super(name, age);
    }
}

const teacher = new Teacher('Mike', 39, 'Moth');
teacher.greeting();
出力結果
$ node dist/class.js
hello readonly. I'm 39
I am a teacher and I teach Moth
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1