在TypeScript中,ES5定义中的OmitThisParameter是什么作用?

4

我在TypeScript的ES5定义中发现了这种类型,但是由于简单的描述有点模糊,所以想知道它的作用。

/**
 * Removes the 'this' parameter from a function type.
 */
type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends (...args: infer A) => infer R ? (...args: A) => R : T;

源代码

这个描述意味着this是一种类型,但当你查看代码时,它的具体含义并不清晰。

我已经在TypeScript的Microsoft文档中搜索过了,但似乎没有涉及到如何使用或为什么要使用this

以下是我看到过使用它的源代码示例。

export class Example {
   funcRef: OmitThisParameter<()=> void>;
   func() { }
   constructor() { this.funcRef = this.func.bind(this); }
}

在这里我看不出任何静态类型的优势。使用funcRef似乎没有限制。这可能是因为这样做可以防止funcRef作为构造函数使用?

如果我进行以下更改,源代码将无问题编译。

export class Example {
   funcRef: () => void;
   func() { }
   constructor() { this.funcRef = this.func.bind(this); }
}

这种类型与箭头函数是相同的,但我们不为箭头函数声明类型。

因此,我正在寻找一个解释这种类型优势并说明为什么我们应该使用这种类型的答案,因为我很少看到它被使用。

你能给出一个源代码示例,让TypeScript引发类型警告吗?

1个回答

3

this参数是一个伪参数,你需要在函数签名中首先放置它,并且它表示在函数内部,this上下文将具有定义的类型。这使得函数更加具体化,因为函数的实现和任何调用者都将把它视为特定类型的方法。

例如:

function addX(this: { x: number }, y: number): number {
  return this.x + y;
}

函数addX()必须绑定到一个具有数字属性x的对象才能成功调用。由于此原因,实现不会抱怨this.x。这防止您以独立方式调用它:
addX(10); // error!  you can't call this function by itself

相反,您必须正确地绑定它...这是一种方法:

const val = {
  x: 123,
  addX: addX
};
val.addX(10); // okay, you're calling it as a method of type {x: number}

如果将其绑定到错误类型的事物上,也会出现错误:

const badVal = {
  x: "whoopsie",
  addX: addX
};
badVal.addX(10); // error! string is not a number, can't do this

因此,带有声明的this参数的函数对其使用的位置更加严格。如果您有一个带有this参数的函数,并且想以未经批准的方式调用它,可以使用OmitThisParameter<>实用程序类型:

const unsafeAddX: OmitThisParameter<typeof addX> = addX; // okay
unsafeAddX(10); // no error (but kablooey at runtime, "this is undefined")

我不一定会推荐这样做,但就像type assertions有用的时候一样,忽略this上下文限制可能也有用。
所以,回到这个问题:
  funcRef: OmitThisParameter<() => void>; // 

那将准确地评估为() => void。类型() => void没有this参数,因此省略它不会有任何影响。真的没有任何理由使用类型OmitThisParameter<() => void>,我怀疑这是一个错误。
看着那个类并眯起眼睛,我可以想象做这样的事情:
export class Example {
  funcRef: OmitThisParameter<Example["func"]>;
  func(this: Example) {}
  constructor() {
    this.funcRef = this.func.bind(this);
  }
}

我已经将限制条件this添加到func()方法中(你可能认为在实际的类方法上下文中,this自动发生,但是它们并没有。这会使编译器变慢,我想。),然后使funcRef的类型与解除限制的func相同。这导致以下行为:
const x = new Example();
const func = x.func;
func(); // error! bad this context
const funcRef = x.funcRef;
funcRef(); // okay

哦,希望这有所帮助。祝你好运!

链接到代码


非常感谢!这一切对我来说都很清晰,而执行 Example ["func"] 也非常聪明。现在我明白为什么这个例子有点毫无意义,以及为什么我之前无法理解它了。 - Reactgular

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接