关于修改ts中this的类型

666 阅读2分钟

ts 在某些时候会自动推导的 this 指向,如:

interface objInterface {
  name: string;
  funa: () => void;
}

const obj: objInterface = {
  name: "name in obj",
  funa() {
    console.log("this", this); // obj
  },
};

假如我们通过 obj.funa() 的方式调用函数,这是没有问题的,但是有时候我们也会通过其他方式调用对象里面的函数,

interface objInterface {
  name: string;
  funa: () => void;
}

const obj: objInterface = {
  name: "name in obj",
  funa() {
    console.log("this", this); // 这里的this指向了obj2,但是类型推断任然为obj
  },
};

const obj2 = {
  name: "name in obj2",
  age: 18,
};
obj.funa.call(obj2);

这个时候虽然我们知道 funa 中的 this 指向了 obj2,但是 ts 的编译器不知道,所以我们需要自己指定 funa 中的 this 指向。

1. 在函数的参数中加入一个 this,并且明确指明其类型

const obj: objInterface = {
  name: "name in obj",
  funa(this: typeof obj2,num: number) {
    console.log("this", this)
  },
};

// 或者直接在接口上指定this的类型
interface objInterface {
  name: string;
  funa: (this: typeof obj2, num: number) => void;
}
image.png

这样 this 的类型被修改指向了 obj2,这样做的好处在于,虽然新增了一个参数,但是并不会对函数接受参数造成影响

image.png

输出结果为

image.png

这是因为 this 参数会在编译后被抹除,所以不会对函数的参数有影响。但是假如 obj 中有很多的函数,每个函数的 this 类型都这样改变会很繁琐,所以还可以使用 ts 的一个工具方法来指定 this 类型。

2. 使用 ThisType 来修改 this 类型

通过 ThisType 我们可以在对象字面量中键入 this,并提供通过上下文类型控制 this 类型的便捷方式。这个功能需要设置 "noImplicitThis": "true" 后才能使用。

ThisType的使用:

const obj: objInterface & ThisType<typeof obj2> = {
  name: "name in obj",
  funa(num) {
    this; 
    /**
        this: {
         name: string;
         age: number;
         }
        this指向了obj2的类型
    */
  },
};

ThisType接受一个泛型,并且会返回这个泛型作为当前字面量的上下文类型,通常会将ThisType<T>和对象自身的类型做交集。对象字面量方法中 this 的类型即为 T

总结

在对象字面量方法中的 this 类型,将由以下决定:

  • 如果这个方法或者方法的类型中显式指定了 this 参数,那么 this 具有该参数的类型。
  • 如果 noImplicitThis 选项已经启用,并且对象字面量的类型中有 ThisType<T> 键入的上下文类型,那么对象的 this 的类型为 T
  • 如果 noImplicitThis 选项已经启用,函数中的 this 具有该对象字面量的类型。
  • 如果函数没有对象做上下文(如:定义一个普通函数),函数的 this 的类型为 any

参考: 1.《深入理解 TypeScript