typescript的this所指问题

发布于 2022-09-13 00:51:33 字数 604 浏览 23 评论 0

按照mongoose官网的virtual例子如下:

personSchema.virtual('fullName').get(function () {
  return this.name.first + ' ' + this.name.last;
})

在ts会被报错为:
“this”隐式具有类型“any”,因为它没有类型批注。ts(2683):“this”的外部值被此容器隐藏

找了一圈在 stackoverflow 上找到了答案

personSchema.virtual("username").get(function(this: { firstName: string, lastName: string}) {
  return this.firstName + " " + this.lastName ;
}) ;

但是为什么会这样呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

失眠症患者 2022-09-20 00:51:33

首先声明,我对 mongoose 不熟,回答是基于 TypeScript 语法知识来进行的

抄下用例代码

personSchema.virtual('fullName').get(function () {
  return this.name.first + ' ' + this.name.last;
})

分析理解为:.get(fn) 通过注释函数的方式扩展功能,这个函数中可以使用 this 来访问目标对象(不过我不知道这个目标对象是什么),这个目标对象包含一个 name 属性,而且 name 是包括 firstlast 属性的对象,所以这个 this 可以用一个类型来表示:

interface SomeObject  {
    name: {
        first: string,
        last: string;
    }
}

现在,通过 get 注入的函数是一个独立的函数,而不是定义在某个类或者对象上的“方法”函数,所以它本身不携带 this 类型。因此,在函数中使用 this,就会被 TypeScript 推导为 any 类型(不过我认为推导为 unknown 更合理)。

就 JavaScript 来说,一个函数确实可以在使用时绑定到某个对象上,因此其内部可以使用 this。这种情况下,假设开发者已经明确了 this 的类型。只不过开发者明确,TSC 并不知道,所以需要告诉 TSC this 的类型 —— 只需要在函数的第一个参数位置声明一个特殊参数 this 的类型就好(这个参数不对应实参传入),然后这个函数可以声明为

function(this: SomeObject) {
    return `${this.name.first} ${this.name.last}`;
}

合起来就是

interface SomeObject  {
    name: {
        first: string,
        last: string;
    }
}

personSchema.virtual('fullName').get(function (this: SomeObject) {
  return this.name.first + ' ' + this.name.last;
}

到于 StackOverflow 上拿到的答案,是在认定 this 类型是如下定义的(使用时没预先定义,直接使用的匿名类型):

interface Blabla {
    firstName: string;
    lastName: string;
}

注意,这和原本出现问题的代码中 this 的类型是完全不一致的,所以到底 this 类型该如何定义,要根据实际情况来决定。


在我的 TypeScript 课程「]TypeScript从入门到实践 【2021 版】」的第五章第 5 节,1 分 28 秒开始就在讲「this 参数」:

image.png

旧街凉风 2022-09-20 00:51:33

找了一圈在 stackoverflow 上找到了答案

UserSchema.virtual("username").get(function(this: { firstName: string, lastName: string}) {
  return this.firstName + " " + this.lastName ;
}) ;

但是为什么会这样呢?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文