解决 TypeScript 中的 ‘this’ implicitly has type ‘any’ 错误

当我们在类之外或在无法推断 this 类型的函数中使用 this 关键字时,会出现“this implicitly has type any”的错误。 要解决此错误,需要将 this 关键字的类型作为函数中的第一个参数。

class Employee {
  constructor(public name: string, public salary: number) {
    this.name = name;
    this.salary = salary;
  }
}

interface Employee {
  getSalary(): number;
}

// 添加一个指明 this 类型的参数
Employee.prototype.getSalary = function (this: Employee) {
  return this.salary;
};

const e1 = new Employee('Tom', 100);

console.log(e1.getSalary());

当 TypeScript 无法确定 this 关键字的类型时,会出现“this implicitly has type any”错误,因为我们已经在类之外或嵌套函数中使用了它。

在类之外使用时,默认情况下它的类型为 any。

以下是会产生错误的代码示例:

class Employee {
  first: string;
  last: string;

  constructor(first: string, last: string) {
    this.first = first;
    this.last = last;
  }

  getFullNameFunction() {
    return function () {
      // 错误 'this' implicitly has type
      // 'any' 因为它没有类型注释。
      return this.first + ' ' + this.last;
    };
  }
}

解决 Typescript 中的 'this' implicitly has type 'any' 错误

注意 ,getFullNameFunction 中嵌套函数内部的 this 上下文不是 Employee 实例。

为了解决这种错误,我们必须将嵌套函数转换为箭头函数,因为箭头函数使用封闭作用域的 this。

class Employee {
  first: string;
  last: string;

  constructor(first: string, last: string) {
    this.first = first;
    this.last = last;
  }

  getFullNameFunction() {
    return () => {
      console.log(this);
      // 现在 this 是 Employee 的实例
      return this.first + ' ' + this.last;
    };
  }
}

const e1 = new Employee('John', 'Doe');

const func = e1.getFullNameFunction();

console.log(func()); // "John Doe"

由于嵌套箭头函数中的 this 引用了一个 Employee 实例,因此我们不再收到错误消息。

或者,我们可以使用闭包。

class Employee {
  first: string;
  last: string;

  constructor(first: string, last: string) {
    this.first = first;
    this.last = last;
  }

  getFullNameFunction() {
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    const self = this; 
    return function () {
      // this 指向Employee实例
      return self.first + ' ' + self.last;
    };
  }
}

const e1 = new Employee('John', 'Doe');

const func = e1.getFullNameFunction();

console.log(func()); // "John Doe"

我们将它分配给外部函数中名为 self 的变量。 现在嵌套命名函数可以使用 self 变量,它引用 Employee 的一个实例。

当 tsconfig.json 文件中的 noImplicitThis 属性设置为 true 时,TypeScript 会在没有显式类型的情况下使用它时抛出错误。

注意,有时 TypeScript 甚至可以在类之外推断出 this 的类型。

为了解决这个错误,我们经常不能使用 this 参数并显式设置 this 的类型。

如果无法通过将其设置为特定类型来解决错误,可以尝试将其类型设置为 any

如果想在 this 被隐式指定为 any 类型时禁用错误报告,可以在 tsconfig.json 文件中将 noImplicitThis 属性设置为 false。

{
  "compilerOptions": {
    // ... 其他设置
    "noImplicitThis": false
  }
}

现在,当 this 被隐式设置为 any 类型时,TypeScript 不再会抛出错误。