繁体   English   中英

打字稿:“新”调用函数

[英]typescript: 'new' call to function

最近我想到将我的一个副项目转换成 Typescript。 但是我在使用 new 调用函数时遇到了麻烦。

我正在尝试调用从另一个文件导入的函数,如下所示:

// Function in 'file.js'
function Foo() {
  this.x = 1;
  this.y = 2;
}
Foo.prototype.set = function() {
   return this.x + this.y;
};
export { Foo };
// Function in another file calling Foo
import { Foo } from './file';
function getSum() {
  let foo = new Foo(); // I got the below error here!!!
  foo.set();
}

当我尝试键入此内容时,出现此错误: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. .


查看打字稿文档,我理解调用签名应该写成如下:

type SomeConstructor = {
  new (s: string): SomeObject;
};
function fn(ctor: SomeConstructor) {
  return new ctor("hello");
}

但我不知道如何将上述类型应用于我的“Foo”函数。 我试图将构造签名应用于函数,但无法正确放置。

// Function in 'file.js' --> renamed to 'file.tsx'
type FooType = {
  x: number,
  y: number,
};

type FooConstructor = {
  new (): FooType
};

function Foo(this: FooType) { // How do I add FooConstructor to this?
  this.x = 1;
  this.y = 2;
}
Foo.prototype.set = function(): number {
   return this.x + this.y;
};

我无法在导出/导入或函数调用期间应用它。 以下所有抛出错误。

export { Foo: FooConstructor };
import { Foo: FooConstructor } from './file';
let foo = new Foo() as FooConstructor;

那么我是否应该将 Foo 函数更改为一个类,这是唯一可能的输入方式吗?。 我看到很多博客展示了如何键入一个类,但即使使用这种方法,我也收到一条错误消息,说Type 'FooType' is not assignable to type 'FooConstructor'

我在这里迷路了。 任何帮助表示赞赏!


编辑:我的 File.ts 现在看起来像这样:

我在 File.ts 文件中添加声明,如下所示:

type FooType = {
  x: number,
  y: number,
};

declare class Foo {
  constructor();
  x: number;
  y: number;
  setHeader(): number;
}

function Foo(this: FooType) {
  this.x = 1;
  this.y = 2;
}
Foo.prototype.set = function(): number {
   return this.x + this.y;
};

export { Foo };

如果您有需要作为 TypeScript 类型化的遗留 JavaScript 代码,您可以创建仅包含类型的定义文件(运行时代码保留在 JavaScript 中)。

在最初的示例中,一个包含用 ES5 编写的Foo类的file.js文件可能有一个包含以下内容的同级file.d.ts

// file.d.ts
export declare class Foo {
  x: number;
  y: number;
  constructor();
  set(): number;
}

// Any other TypeScript file
import { Foo } from 'any/path/file';
let foo = new Foo(); // Foo
const num = foo.set(); // number

所以问题中的错误是将遗留的 JavaScript 代码移动到 TypeScript 文件(TypeScript 不支持 ES5 作为源代码,至少对于类)而不是编写定义文件。

注意:在这个具体的例子中, constructor(); 是多余的,因为它是隐式默认构造函数,但您可以使用任意数量、任意类型的参数键入构造函数,甚至可以利用函数重载来定义多个签名。

打字游乐场

作为对“如何键入一个不是作为 ES6 类编写的新函数?”的更一般的回答,也可以在任何 TypeScript typeinterface中使用new关键字:

interface Foo {
  x: number;
  y: number;
  set(): number;
}

type Constructor<T> = new (...args: any[]) => T;

declare const newableFunction: Constructor<Foo>;

const obj = new newableFunction(); // Foo

打字游乐场

同样在这种情况下,如果实现是一个普通的旧函数,最好将它编写在一个单独的 JavaScript 文件中,否则编译器会抱怨声明的类型与实现的类型不匹配。

更进一步,考虑这种混合函数,它可以使用或不使用new关键字来调用:

// Function in 'file.js'
function newableFunction() {

  const self = Object.getPrototypeOf(this) === newableFunction.prototype ? this : {};

  self.x = 1;
  self.y = 2;
  self.get = function () {
    return self.x + self.y;
  }
  return self;
}

这个特殊函数可以这样输入:

interface Foo {
  x: number;
  y: number;
  get(): number;
}

interface Constructor<T> {
  (...args: any[]): T
  new (...args: any[]): T
}

export const newableFunction: Constructor<Foo>;

使用示例:

import { newableFunction } from './file';

const foo1 = newableFunction(); // Foo
const foo2 = new newableFunction(); // Foo

这种构造也可以在lib.es5.d.ts原生 JavaScript 类型中找到,例如Number构造函数:

interface NumberConstructor {
    new(value?: any): Number;
    (value?: any): number;
    // ...

正式地,Typescript 决定不为这种有效的“老派”JavaScript 提供语法支持。 他们更喜欢class语法。

但是,有可能使它工作,从我以前的回答中复制:

// Only instance members here.
export interface Circle { // Name the interface with the same than the var.
  radius: number;
  area: () => number;
  perimeter: () => number;
}

// You could define static members here.
interface CircleConstructor {
  new(radius: number): Circle;
}

export const Circle = function(this: Circle, radius: number) {
  const pi = 3.14;
  this.radius = radius;
  this.area = function () {
    return pi * radius * radius
  }
  this.perimeter = function () {
    return 2 * pi * radius;
  }
} as unknown /*as any*/ as CircleConstructor; // Note the trust-me casting
    
const c = new Circle(3); // okay

这带来了一些问题。 例如,它正在使用any禁止的类型,或者必须使用as操作符,这是非常丑陋的。 作为改进,我使用了unknown而不是any但核心问题仍然存在。 这使得 lint 工具不会报错,所以它比any有了很大的改进。

这是迄今为止我找到的最佳解决方案。 Typescript 开发者意识到了这一点,但他们决定不为这种“语法”提供支持。

in.d.ts 文件或直接 in.ts 文件:

declare class Foo {
    public x: number;
    public y: number;

    set(): number;
}

操场

解决这种情况的唯一方法是将以下 function 转换为 class:

function Foo(this: FooType) { // How do I add FooConstructor to this?
  this.x = 1;
  this.y = 2;
}
Foo.prototype.set = function(): number {
   return this.x + this.y;
};

至:

class Foo() {
  x: number;
  y: number;
  constructor() {
    this.x = 1;
    this.y = 2;
  }
  set (): number {
   return this.x + this.y;
  }
}
>Adjunto mi código espero ayude
>Para ejecutar solo realice new Functions() 
>para llamar a la clase internamente se ejecutar
> el constructor de Functions

type SomeConstructor = {
  new (s:string):SomeObject;
}


type SomeObject = any;


export class Example{
   constructor(s:string){
     console.log(s)
   }
}


 export class Functions {
    constructor(){
      const callable = (someObject:SomeObject)=>{
        return someObject;
      }

      this.fnSomeConstructor(callable(new Example("Hola")));
    }

   fnSomeConstructor(ctor: SomeConstructor) {
    return new func(func.name);
   }
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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