在 Typescript 中为“this”关键字键入注释

Type annotation for `this` keyword in Typescript

提问人:AndrewE 提问时间:7/22/2017 更新时间:10/23/2021 访问量:10648

问:

我有一个独立的函数,旨在使用 提供的上下文。Function.prototype.call

例如:

function foo () {
    return this.bar;
}

> foo.call({bar: "baz"})
baz

在这种情况下,有没有办法为关键字提供 Typescript 类型注释?this

JavaScript 打字稿

评论

2赞 toskv 7/22/2017
它有一个类型是 .在这种情况下,这也是正确的类型,因为可以使用任何对象调用该函数。如果你想要更严格的类型,你可以只获取对象作为参数,然后以这种方式键入它。any

答:

30赞 jcalz 7/22/2017 #1

首先,您可以使用特殊的 this 参数语法来标识您期望的对象类型:this

function foo (this: {bar: string}) {
    return this.bar; // no more error
}

如果您直接调用它,这会有所帮助:

foo(); // error, this is undefined, not {bar: string}

var barHaver = { bar: "hello", doFoo: foo };
barHaver.doFoo(); // acceptable, since barHaver.bar is a string

var carHaver = { car: "hello", doFoo: foo };
carHaver.doFoo(); // unacceptable, carHaver.bar is undefined

TS3.2+ 更新

TypeScript 3.2 引入了 --strictBindCallApply 编译器选项,该选项强类型函数的 .call() 方法。如果您使用它(或包含此的 --strict 编译器功能套件),则该参数还将强制执行所需的行为:thisfoo.call()

foo.call({ bar: "baz" }); // okay
foo.call({ baz: "quux" }); // error!

Playground 代码链接


TS3.2 之前的答案如下:

但是你想使用 .不幸的是,TypeScript 中的键入不会真正为您强制执行此限制:foo.call()Function.prototype.call()

foo.call({ bar: "baz" }); // okay, but
foo.call({ baz: "quux" }); // no error, too bad!

将更好的东西合并到 TypeScript 的声明中给我带来了问题,(丑陋的第一点;你需要强制转换为某些东西),所以你可以尝试这样的事情:Functionfoo

interface ThisFunction<T extends {} = {}, R extends any = any, A extends any = any> {
  (this: T, ...args: A[]): R;
  call(thisArg: T, ...args: A[]): R;
}

A 是一个函数,其类型为 a,返回值为 类型,rest 参数类型为 。(丑陋的第二点:你不能轻易地指定多个不同类型的参数,而这种方式将由类型系统强制执行。ThisFunction<T,R,A>thisTRA[]

然后你可以转换为 ,(丑陋的第三点:类型系统只是不会推断类型),最后使用:fooThisFunction<{ bar: string }, string>thiscall()

(<ThisFunction<{ bar: string }, string>>foo).call({ bar: "baz" }); // okay, and
(<ThisFunction<{ bar: string }, string>>foo).call({ baz: "quux" }); // error, hooray!