首页 > 解决方案 > 打字稿函数重载:无法访问的“this”类型

问题描述

我正在尝试将属性分配给类实例,其中属性的签名是this作为类型传递的函数。

function create<R>(returnValue: R) {
  function wrap(d?: string): R | string {
    if (d) return d
    return returnValue
  }
  return wrap
}

class A {
  prop = create(this)
}

只要从返回的函数create没有重载,它就可以工作。

function create<R>(returnValue: R) {
  // if no argument, return returnValue
  // otherwise return the argument
  function wrap(d: string): string
  function wrap(): R
  function wrap(d?: string): R | string {
    if (d) return d
    return returnValue
  }
  return wrap
}

一旦我重载返回的函数以根据传入的参数优化返回类型,TypeScript 就会抱怨:

The inferred type of 'prop' references an inaccessible 'this' type. A type annotation is necessary.

我很乐意添加类型注释,但我尝试过的每个签名都有完全相同的问题。

this值硬编码到类A中是行不通的,因为我还希望能够支持子类化。

我不确定如何解决这个问题。只要结果类型正确,就很高兴在类中添加丑陋的 hack。

function create<R>(returnValue: R) {
  // if no argument, return returnValue
  // otherwise return the argument
  function wrap(d: string): string
  function wrap(): R
  function wrap(d?: string): R | string {
    if (d) return d
    return returnValue
  }
  return wrap
}

class A {
  // Currently gives the error:
  // The inferred type of 'prop' references an inaccessible 'this' type. A type annotation is necessary.
  // If we remove the overloading from the wrap function above, this part works,
  // but it breaks the chaining interface because it doesn't know if the result of new A().prop()
  prop = create(this)
}

class B extends A {
  isB = true // something to differentiate (prevents hardcoding A as return type)
}

const a: A = new A().prop()
const b: B = new B().prop()
b.prop('something')

游乐场链接

也将不胜感激任何解释为什么这不起作用。

标签: typescript

解决方案


啊,我想我找到了一个解决方案:返回this并将this类型参数移出函数创建器并移入函数签名:

function create() {
  // if no argument, return this
  // otherwise return the argument
  function wrap<R>(d: string): string
  function wrap<R>(): R
  function wrap<R>(this: R, d?: string): R | string {
    if (d) return d
    return this
  }
  return wrap
}

class A {
  // Currently gives the error:
  // The inferred type of 'prop' references an inaccessible 'this' type. A type annotation is necessary.
  // If we remove the overloading from the wrap function above, this part works,
  // but it breaks the chaining interface because it doesn't know if the result of new A().prop()
  prop = create()
}

class B extends A {
  isB = true // something to differentiate (prevents hardcoding A as return type)
}

const a: A = new A().prop()
const b: B = new B().prop()
b.prop('something')

游乐场链接

我通过进一步简化问题发现了这一点


推荐阅读