2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【typescript】classのconstructorを省略していけない!!

Posted at

あるエンジニアがjavascriptを使用して開発を行っていたが、開発速度をあげるためにtypescriptを導入した。
型を定義することで変数の中身が明確になったりと、開発速度があがった。
しかし、型の定義を行っているはずが、型のバグに悩まされていた。

結論からいうと、tsconfigは厳しめに設定すべきだった

型を定義しても、それにそっていない内容のものがあり、想定外のところでバグを起こしてしまっていた。
以下のような例があげられる。


と、その前にクラスについて

クラスのインスタンス

インスタンス化、つまり、newしたものがインスタンス
newしていないものはインスタンスでない。インスタンスでないと、クラスメソッドなどを使用できない。

以下はただの object を型アサーションで User にしたもの。
インスタンスではないので、クラスメソッドの getFullName を使用できない。(TypeErrorになる。)

class User {
  public id: string;
  public firstName: string;
  public lastName: string;

  constructor (input?: Partial<User>) {
    this.id = input?.id ?? "id"
    this.firstName = input?.firstName ?? "firstName"
    this.lastName = input?.lastName ?? "lastName"
  }

  getFullName(): string {
    return `${this.firstName} ${this.lastName}`
  }
}

const _user = {
  id: "id",
  firstName: "firstName",
  lastName: "lastName"
}

{
  const user = _user as User;

  console.log(_user instanceof User) // false
  console.log(user instanceof User) // false

  console.log(user.getFullName()) // TypeError: user.getFullName is not a function
}

{
  const user = new User(_user);

  console.log(user instanceof User) // true

  console.log(user.getFullName()) // firstName lastName
}

constructorを省略

constructorを省略することで以下のような型と違う状況が起きる可能性がある。

class User {
  id: string;
  name: string;
}

const _user = new User();
_user.id = "id";
console.log(_user.name) // undefined

const user = new User();
user.id = "id";
user.name = "name";
console.log(user.name) // name

ただの型なのか、classを用意すべきかは考えたほうがいい。
もし型だけなら以下のようにする。

type User = {
  id: string;
  name: string;
}

const _user: User = {
  id: "id"
};
// Property 'name' is missing in type '{ id: string; }' but required in type 'User'.
// 'name' is declared here.

const user: User = {
  id: "id",
  name: "name"
};

console.log(user) // { id: 'string', name: 'string' }

クラスを用意するならconstructorを定義する

class User {
  id: string;
  name: string;

  constructor (input?: Partial<User>) {
    this.id = input?.id ?? "id"
    this.name = input?.name ?? "name"
  }
}

const user = new User()
console.log(user.name) // name

delete(オブジェクトからプロパティを削除)

deleteにも要注意。型アサーションと同様のことが起きる。

class User {
  id: string;
  name: string;

  constructor (input?: Partial<User>) {
    this.id = input?.id ?? "id"
    this.name = input?.name ?? "name"
  }
}

const user = new User()
delete user.name
console.log(user.name) // undefined

他にもany型など開発者を泣かせるtypescriptの仕様がある。

以下のような記事にもあるとおり、 asany はtypescriptの効果をなくしてしまう。

敗北者のTypeScript


Docs

typescript: https://www.typescriptlang.org/


やるからには厳しくせなあかんな
(やるからには厳しくしないといけないな)

2
1
2

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?