打字稿 + ES6 代理

Posted

技术标签:

【中文标题】打字稿 + ES6 代理【英文标题】:Typescript + ES6 Proxy 【发布时间】:2020-08-30 18:29:56 【问题描述】:

ES6 Proxy.apply 方法提供了一种使用没有“new”关键字的类的方法。

但在 TypeScript 上,它会给出错误“'typeof ClassName' 类型的值不可调用。您的意思是包含 'new' 吗?”。

有什么方法可以防止 TypeScript 错误?

这是一个简单的例子;

class ClassName 
  constructor(anyThing?: any) 
    if (anyThing) 
      // Do something
    
  


// ES6 Proxy
const CustomName = new Proxy(ClassName, 
  apply: (Target, _thisArg, argumentsList) => 
    return new Target(...argumentsList);
  
);

// Test ---------
new ClassName("test"); // return ClassName  

// No error
new CustomName("test"); // return ClassName  

// javascript: no error
// TypeScript: error => Value of type 'typeof ClassName' is not callable. Did you mean to include 'new'?
CustomName("test"); // return ClassName  

【问题讨论】:

【参考方案1】:

使用 Target 的静态方法使 Proxy 可调用

class ClassName 
  constructor(anyThing?: any) 
    if (anyThing) 
      // Do something
    
  

  // Forge
  static forge (anyThing?: any) 
    return new ClassName(anyThing);
  


// ES6 Proxy
const CustomName = new Proxy(ClassName, 
  apply: (Target, _thisArg, argumentsList) => 
    return new Target(...argumentsList);
  
) as typeof ClassName & typeof ClassName.forge;

let instance: ClassName;

instance = new ClassName();
instance = new CustomName();
instance = CustomName();

【讨论】:

这是完全有效的 TS & JS。那里没有错误。见typescriptlang.org/play/…【参考方案2】:

Typescript 无法理解您的 apply 函数对类的作用。您将需要扩充类型。

解决方案 (playground)

class ClassName 
  constructor(anyThing?: any) 
    if (anyThing) 
      // Do something
    
  


// ES6 Proxy
const CustomName = new Proxy(ClassName, 
  apply: (Target, _thisArg, argumentsList) => 
    return new Target(...argumentsList);
  ,
  get: () =>  ... , // Implement static method(s)
) as typeof ClassName & (() => ClassName) &  staticMethod(): CustomName ;

let instance: ClassName;

instance = new ClassName();
instance = new CustomName();
instance = CustomName();
instance = CustomName.staticMethod();

【讨论】:

谢谢,这是教 TypeScript 的一个好技巧,它是可调用的。可以引用函数还是静态方法? 我添加了一个静态方法类型定义。要执行类方法,您需要类实例的另一个代理。 我不是那个意思。我的意思是作为一个静态 create() 方法返回 new ClassName()。并将 CustomName 转换为 create() 方法。 - 如果一个静态方法不可用,至少一个函数。 您能说明您希望如何使用该功能吗?我不明白。 我添加了下一个答案。当然,不能引用构造方法。

以上是关于打字稿 + ES6 代理的主要内容,如果未能解决你的问题,请参考以下文章

ES6 字符串文字/打字稿的 Chrome 开发工具问题

在带有 loadClass 的打字稿中使用 es6 类和猫鼬

打字稿:如何根据对象键/值类型在 ES6 映射中创建条目

打字稿和嵌套解构

如何使用打字稿来监听对象更改?

更改打字稿目标会影响编译性能吗?