網站搜尋

typescript - 創建只允許普通函數而不允許箭頭函數的類型


我正在設定一種類型,允許開發者將特定屬性定義為函數。在背後,這個屬性會使用 call() 方法被調用,並且我會改變 this。此外,我允許開發者訪問新的 this 的某些屬性(我使用特殊的 this 參數設置這些屬性,這個參數告訴 TypeScript 該函數內 this 的類型)。當然,這僅適用於普通函數,因為箭頭函數無法使用 call() 改變 this,但是我無法找到方法創建一個類型來阻止開發者使用箭頭函數。以下是一個能夠展示這個問題的簡單範例:

type Effect = {
  irrelevantProp?: any;
  irrelevantProp2?: any;
  // `this` type is changed to MyClass (with limited access)
  specialFunc(this: Pick<MyClass, 'firstName' | 'lastName'>, a: number, b: number): string;
}

class MyClass {
  constructor(public firstName: string, public lastName: string, private effect: Effect) {}

  doThing() {
    // calls specialFunc() while passing self as `this`
    this.effect.specialFunc.call(this, 5, 7);
  }
}

// good
const effectNormal: Effect = {
  specialFunc(a, b) {
    console.log(this.firstName);
    console.log(this.lastName);
    return 'blabla';
  },
}

// good
const effectNormal2: Effect = {
  specialFunc: function(a, b) {
    console.log(this.firstName);
    console.log(this.lastName);
    return 'hello';
  },
}

// bad
const effectArrow: Effect = {
  specialFunc: (a, b) => { // no error
    console.log(this.firstName); // error
    console.log(this.lastName); // error
    return 'whatever';
  }
  // There's no error on the usage of the arrow function itself, but I WANT an error there
}

如你所見,當在箭頭函數中使用 this 時,TypeScript 已經會產生錯誤,因為它可能未定義,所以編譯器顯然理解箭頭函數與普通函數之間的差異。

經過大量的 Google 搜尋,我仍然不知道如何製作一個類型定義來識別 TypeScript 明顯知道的那種差異。我找到的最接近的東西是這個「如何使用 TypeScript 編譯器 API 檢測箭頭函數」,但我需要的是可以在編譯時檢查的東西。