LoginSignup
3
0

More than 3 years have passed since last update.

TypeScriptで 'Uncaught TypeError: this.arrow is not a function'

Last updated at Posted at 2019-12-04

はじめに

表題のエラーに遭遇したので、解決方法を探りました。
この記事は、表題の問題の詳細と解決方法を共有するためのものです。

発生環境

TypeScript 3.7.2

問題の詳細

発生した問題

コンストラクタ内で特定のアロー関数がundefinedとなります。

pen.js:32 Uncaught TypeError: this.arrow is not a function
    at ExtendClass.init (pen.js:32)
    at ExtendClass.BaseClass (pen.js:14)
    at new ExtendClass (pen.js:24)
    at pen.js:36

問題が発生する最小限のコード

class BaseClass {
  constructor()
  {
    this.init();
  }

  init():void{
    console.log("init Base Class");
  }
}

class ExtendClass extends BaseClass{
  constructor(){
    super();
  }

  init():void{
    super.init();
    this.arrow();
  }

  arrow = () =>{
    console.log("Arrow func");
  }
}

const instance = new ExtendClass();
console.log( instance );

CodePenはこちらです。

問題の発生手順

問題が発生する手順は

  1. 基底クラスを定義する
  2. 基底クラスのコンストラクタ内で関数を呼び出す
  3. 基底クラスを継承した拡張クラスを定義する
  4. 拡張クラスで手順2の関数をオーバーライドする
  5. 手順4の関数内部でアロー関数を呼び出す

となります。

問題の原因

TypeScript Playgroundで上記のコードをJavaScriptに変換すると、以下のコードとなります。

"use strict";
class BaseClass {
    constructor() {
        this.init();
    }
    init() {
        console.log("init Base Class");
    }
}
class ExtendClass extends BaseClass {
    constructor() {
        super();
        this.arrow = () => {
            console.log("Arrow func");
        };
    }
    init() {
        super.init();
        this.arrow();
    }
}
const instance = new ExtendClass();
console.log(instance);

原因はここです。

    constructor() {
        super();
        this.arrow = () => {
            console.log("Arrow func");
        };
    }

アロー関数がコンストラクタの内部で宣言されています。したがってExtendClass.init関数が実行された時点でarrow関数はまだ定義されていません。

解決方法

アロー関数ではなく通常の関数にする

class ExtendClass extends BaseClass{
...中略...
  arrow():void{
    console.log("Arrow func");
  }
}

アロー関数を使う必要がないなら、通常の関数に置き換えるのが最も簡単な解決方法です。

オーバーライドした関数からは呼び出さず、コンストラクタ内から呼び出す

class ExtendClass extends BaseClass{
  constructor(){
    super();
    this.arrow();
  }

  arrow = () =>{
    console.log("Arrow func");
  }
}

設計上アロー関数でなくてはいけない場合、コンストラクタの内部で呼び出すことでこの問題を回避できます。
アロー関数は定義後に実行されます。

以上、ありがとうございました。

3
0
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
3
0