打字稿:是否可以使用函数声明类

时间:2020-04-27 20:42:58

标签: typescript

通过阅读本教程,我发现在Typescript中声明类的一种方法是像这样使用class语法。

class Person { 
   constructor(name: string) {
      this.name = name
   }
}

编译后将生成以下Javascript代码。

//Generated by typescript 1.8.10
var Person = (function () {
   function Person(name) {
      this.name = name
   }
   return Person;
}());

我的问题是,是否可以像这样使用生成的Javascript语法在Typescript中声明一个类?

function Person(name: string) {
  this.name = name
}

2 个答案:

答案 0 :(得分:2)

根据microsoft/TypeScript#2310,这可能是,但不建议使用。根据TS小组的说法,如果您使用的是TypeScript,则应直接使用class。如果目标是ES2015或更高版本,则将按原样编译,如果目标是ES5,则将编译为您提到的功能。

如果要忽略该建议,则必须执行一些类型注释和断言才能获得所需的行为,并且最终将在编译输出中留下一些运行时无操作代码。而且它不是特别安全的类型(如果您在键入过程中犯了错误,编译器将不会抱怨)。

首先,您必须手动定义类实例的接口,因为编译器无法为您推断出它:

interface Person {
    name: string;
}

然后,您必须给函数一个this parameter,以便编译器理解在函数的实现内部,this值应被视为类的实例。您还应该将函数从Person重命名为其他名称(例如_Person),因为在之后,您将无法将其类型更改为new-。事实:

function _Person(this: Person, name: string) {
    this.name = name;
}

最后,您可以将Person定义为const,其值与运行时重命名的函数相同,但在编译时给它一个构造函数签名:

const Person = _Person as any as new (name: string) => Person;

现在已设置为Person是运行时的函数(即使您以ES2015 +为目标,也不是class),但是编译器将其视为构造函数:

const p = new Person("Alice");
console.log(p.name); // Alice

所以,嗯,万岁?在任何生产环境中,像这样与编译器抗争并“取胜”可能都不值得。但是,我想看看如何做到这一点很有趣。

好的,希望能有所帮助;祝你好运!

Playground link to code

答案 1 :(得分:1)

作为对已有答案的改进,您也可以采用以下方式:

python2

这样,即使您仍然在乎这些内容,也可以保留一些类型安全性。


通过这种方式,您还可以通过先将静态方法添加到interface Person { name: string; } interface PersonConstructor { new(name: string): Person; } const Person: PersonConstructor = function (this: Person, name: string) { this.name = name; } as any; const p = new Person("Alice"); console.log(p.name); // Alice 来在Person上定义静态方法。因此,您可以这样做:

PersonConstructor

然后再做:

interface PersonConstructor {
    new(name: string): Person;
    foo(bar: string): void;
}

并用Person.foo = (bar: string) => { console.log(`foo ${bar}`); }

调用

Playground Link