有什么方法可以绕过 ts 2339 访问 class 方法,或者是否可以在打字稿中的 class 之外定义 class 方法?

is there any way to bypass ts 2339 in to access class methods OR is it possible to define class methods outside of class in typescript?

我打算做的事情如下

class A {
  constructor() {
    bind(this); 
  }
  hello(){
    this.method1();  // <-- I will get error at this line saying method one does not exist on typeOf A
  }
}
function bind(thisReference) {
  function method1() {
    console.log('in method 1');
  }
  thisReference.method1 = method1.bind(thisReference)
}
var a = new A();
a.hello();

请注意,在其他情况下我们得到 ts2339 的对象,可以通过定义类型或使用 any

来解决,我特别想解决这种情况因此是单独的问题。在react中定义class个组件时非常有用,这样我们就可以很方便的在class上定义新的方法在class.

之外

正如@bergi 所说,您需要让它们成为类型的静态部分。

我熟悉的更常见的模式是使用 HoCs 通过 props

提供额外的行为

由于您可以轻松地提供函数作为 prop,这提供了一种从外部提供某些所需行为的可靠方法。

这种运行时 class 突变在静态编译语言中表示并不是超级“安全”。我不确定如果你严格遵守这种模式,在这种情况下你是否真的可以避免 as any 事情。

您需要在 class 主体中声明该方法并在构造函数中分配它:

class A {
  method1: () => void;
  constructor() {
    this.method1 = () => {
      console.log('in method 1');
    };
  }
  hello(){
    this.method1();
  }
}
var a = new A();
a.hello();

您也可以在 class 之外定义函数,但我建议不要这样做:

function method1() {
  console.log('in method 1');
}

class A {
  method1: () => void;
  constructor() {
    this.method1 = method1.bind(this);
  }
  …
}

[解决方案]感谢@Bergi 的启发

这个错误似乎非常有限,我想我最好保留我的 js 文件,然后创建 ts 文件并添加额外的类型

但是我意识到这个错误不是因为 typescript 的规则,而是因为 classes 与函数的不同之处,虽然 javascript 中的 classes 可以转换为函数,但是他们有他们独特的存在

我们当然不能将成员变量绑定到 classes 之外的 classes,但我的主要意图是 class 应该能够将逻辑委托给外部的一些代码class 并且可以通过以下语法来完成,该语法既甜美又简单

import React from 'react';

/** this should not be arrow function so that
 *  caller's execution context can be used as this */
function sayHello() {
  console.log('Hi, these are the props', this.props);
  this.setState({ a: 'hi' });
}

export class Delegate extends React.Component<any, any> {
  state: any = {};
    sayHello = sayHello; // <-- that which adds sweetness!
    /**
     * note the use of arrow function to define hello
     * so that when it calls this.sayHello
     * this actually refers to class instance
     */
  hello = () => {    
    this.sayHello(); // <-- this works totally fine
  };
  render() {
    return (
      <div>
        Delegate Class
        <div onClick={this.hello}>
          this is coming from props {this.props.propName}
          {this.state.a}
        </div>
      </div>
    );
  }
}
---
<Delegate propName="propName" /> //will do as expected
---
var a = new Delegate();
a.hello(); // prints --> 'will work properly'

备注

  1. 我们这里没有使用构造函数
  2. 我们不是在 class 之外绑定,而是直接在 class 声明中绑定

加分 -- 用例

用例可以分为两部分

  1. 假设有两个 classes A 和 B 想要一个方法,那么一种方法是使用 extends,写一个 Class 具有该功能的 Super,另一种方法是正如我们在解决方案中讨论的那样,使用分配给 class 变量的方法,我认为,这种方法是更自由的写作方式,这意味着 A 和 B 可以独立于父级 class.

另一方面,用extends编写代码也是不可扩展的,如果class A和C想要使用另一个函数,我们就得挠头了

  1. 如果没有第1点中描述的用例,那么这种语法有助于减少classA的代码行数,因为它已将函数定义委托给另一个文件。

我更喜欢用尽可能少的代码编写每个文件