简体   繁体   中英

Typescript + ES6 Proxy

ES6 Proxy.apply method serves a way to use classes without a "new" keyword.

But on TypeScript, it gives an error "Value of type 'typeof ClassName' is not callable. Did you mean to include 'new'?".

Is there any way to prevent TypeScript errors?

Here is the simple example of it;

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 { }

Typescript is not able to understand what your apply function does to the class. You will need to augment the type.

Solution ( 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();

Make Proxy callable with Target's static method

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM