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;
}
这样 this 的类型被修改指向了 obj2,这样做的好处在于,虽然新增了一个参数,但是并不会对函数接受参数造成影响
输出结果为
这是因为 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》