Typescript中的type和class有什么区别?

时间:2018-07-02 08:27:58

标签: typescript

typeclass有什么区别?

type Point {
  x: number, y: number
}

let p = new Point();

以上结果为:

  

'Point'仅指一种类型,但在此处被用作值。

为什么会这样?我不一定不是用Point作为值,而是用它来实例化类型。

在什么情况下由于type不适合而需要使用class吗?

4 个答案:

答案 0 :(得分:10)

Typescript在某些方面有两个不同的Universe:值空间和类型空间。类型空间是定义类型的地方,类型会被完全擦除,并且在运行时不存在。值空间包含值,并且显然会在运行时存在。

什么是值?值文字,变量,常量和参数显然是值。函数和类声明也是值,因为它们确实具有运行时对象来备份它们,即函数对象和类构造函数(也是函数)。 枚举也是值,因为它们在运行时由对象备份。

什么是类型?任何带有type关键字的定义都是类型以及接口,类声明枚举

您会注意到我在两个空格中都提到了类声明。类存在于类型空间和值空间中。这就是为什么我们可以在类型注释(let foo: ClassName)和表达式(例如new ClassName())中使用它们的原因。

枚举也跨越两个世界,它们还表示我们可以在批注中使用的类型,还表示将包含枚举的运行时对象。

类型空间和值空间中的名称不会冲突,这就是为什么我们可以定义具有相同名称的类型和变量的原因:

type Foo = { type: true }
var Foo = { value : true } // No error, no relation to Foo just have the same name in value space 

类声明和枚举,因为它们跨越两个空格,将在两个空格中“用完”名称,因此,我们无法定义与类声明或枚举同名的变量或类型(尽管我们可以这样做)合并,但这是一个不同的概念)

在您的特定情况下,Point只是一个类型,我们可以在类型注释中使用它,而不能在需要运行时状态的表达式中使用。在这种情况下,该类型很有用,因为它允许编译器从结构上检查对象文字是否可分配给Point类型:

let p: Point = { x: 10, y: 15 }; // OK
let p: Point = { x: 10, y: 15, z: 10 }; // Error

如果要创建一个类,则需要使用class关键字来完成,因为这将创建一个不仅仅是类型的运行时值:

class Point{
    constructor(public x: number, public y: number){}
}
let p = new Point(10,10)

答案 1 :(得分:2)

您使用type(或在其他情况下为interface)进行类型注释,以指示JavaScript对象的结构:

type Point = {
  x: number, y: number
}

function doSomething(p: Point) {
}

let p: Point = { x: 10, y: 15 };
doSomething(p);

这些类型注释必须进行结构化类型化,这意味着在这种特定情况下,您可以删除类型注释:

let p = { x: number, y: number };
doSomething(p);

一个类完全不同,它为您提供了比JS原型继承更优雅的替代方法:

class Point {
    public x: number;
    public y: number;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    public move(deltaX: number, deltaY: number) {
        this.x = this.x + deltaX;
        this.y = this.y + deltaY;
    }
}

let p = new Point(10, 15);
p.move(1, 2);

当您查看生成的JS代码时,您会很快注意到差异:

The type declaration is dropped in the generated code.

The class definition is turned into a JS function with prototype inheritance

答案 2 :(得分:0)

class myClass extends myParentClass implements myInterface{

}

let value = new myClass();

// value is from type any and from type myClass and from type myParentClass and from type myInterface. Its class is myClass

您只能将new与类名一起使用。但是Point不是一个类名,而是一个值。

class Point{
    private x;
    private y;
    constructor(x,y) {
        this.x = v1;
        this.y = v2;
    }
}

Now Point是一堂课,您可以这样做:

let p = new Point(1,2);

答案 3 :(得分:0)

为了更好地理解,我为所有差异创建了一个表:

| Description                                             | Type | Interface |
|---------------------------------------------------------|------|-----------|
| Describe functions                                      |   ✔  |     ✔     |
| Describe constructors                                   |   ✔  |     ✔     |
| Describe tuples                                         |   ✔  |     ✔     |
| Interfaces can extend                                   |   ≈  |     ✔     |
| Classes can extend                                      |   ✘  |     ✔     |
| Classes can implement                                   |   ≈  |     ✔     |
| Divide another one of its own kind                      |   ✔  |     ≈     |
| Create a union with another one of its own kind         |   ✔  |     ✘     |
| Be used to create mapped types                          |   ✔  |     ✘     |
| Be mapped over with mapped types                        |   ✔  |     ✔     |
| Expands in error messages and logs                      |   ✔  |     ✘     |
| Be completed                                            |   ✘  |     ✔     |
| Be recursive                                            |   ≈  |     ✔     |
Hint: `≈` means partially

也许对于TypeScript的新版本,此表进行了一些更改,如果有,请通过编辑当前帖子来修复该表。