ค้นหาเว็บไซต์

typescript - ทำไม `this` ถึงถูกพิมพ์เป็น `any` ภายในฟังก์ชัน?


ถ้าฉันมีฟังก์ชันในโมดูล, TypeScript อนุญาตให้ฉันทำอะไรบางอย่างเช่น this.unexistingFunction(); (ซึ่ง unexistingFunction ไม่มีอยู่จริง). สิ่งนี้เกิดขึ้นเพราะ this มีชนิดเป็น any ภายในฟังก์ชัน

ทำไมเป็นเช่นนั้น? ในบริบทนี้ไม่มีเหตุผลที่ this จะถูกพิมพ์เป็น any และมันมีแนวโน้มที่จะเกิดข้อผิดพลาดได้ง่าย ตัวอย่างเช่น ถ้าฉันพิมพ์ผิดเป็น this.myFunction(); แทนที่จะเป็นเพียง myFunction(); เพื่อเรียกฟังก์ชันในท้องถิ่น ตัวคอมไพเลอร์ก็จะปล่อยให้ทำแบบนั้นได้ แม้ว่า this.myFunction(); จะไม่อยู่จริงก็ตาม

คำตอบ #1

คุณสามารถเปิดใช้งานตัวเลือก --noImplicitThis true เพื่อจำกัด this ที่มีประเภท any (this:any จะไม่ถูกอนุญาต)

ตัวอย่าง :

class Rectangle {
    //private w: number; //uncomment this line
    //private h: number; //uncomment this line

    constructor(w, h) {
        this.w = w;
        this.h = h;
    }
    getAreaFunction() {
        return () =>  {
            return this.w * this.h;
        };
    }
}
let rectangle = new Rectangle(2, 5);
let areaFunction = rectangle.getAreaFunction();
let area = areaFunction();
console.log(area);

หมายเหตุ: คอมไพล์ด้วย tsc --noImplicitThis

ตรวจสอบสิ่งนี้จาก Typescript Playground

คำตอบ #2

นี่น่าจะเกิดขึ้นเพราะคุณไม่ได้ bind ฟังก์ชันของคุณ ใน JS รวมถึงใน TypeScript ค่า this จะถูกกำหนดโดยผู้เรียกใช้งาน ไม่ใช่ผู้ประกาศ
ซึ่งหมายความว่า ถ้าคุณส่ง callback ระหว่างวัตถุแบบนี้:

const a = {
  a: function() {console.log(this)}
}

const b = {
  b: a.a
}

b.b(); // `this` inside the function will be the instance of `b`, not `a` where it was declared.

สาเหตุทำให้คอมไพเลอร์ TypeScript ไม่สามารถรู้ได้ว่าฟังก์ชันจะถูกเรียกใช้งานที่ใดในเวลาคอมไพล์ ดังนั้นจึงไม่สามารถให้ข้อมูลประเภทได้ ในการแก้ไขปัญหานี้ คุณควร bind ฟังก์ชันนั้น:

class a {
  constructor() {
    a = a.bind(this);
  }

  /* rest of class */
}

หรือใช้ฟังก์ชันลูกศร:

class a {
  const a = () => {};
}

ซึ่งผูกโดยอัตโนมัติเข้ากับบริบทที่ถูกต้อง