以Javascript的思维理解Typescript(二)

51 阅读3分钟

type和interface有什么区别?

interface在上一期中已经基本讲了怎么定义接口类型,以及都有哪些用法,那接下来要解释这个问题,我们还得了解什么是type,它可以干什么事情。

先来一点简单的泛型知识:

function identity(arg: any): any { return arg; }

any是不稳定的,这样定义意味着arg可以是number,也可以是任意类型,如果我想保证入参和出参的类型一致,那我应该写

function identity(arg: number): number { return arg; }

但是我又只是想保持入参出参一致,并不确定是否一定为number类型怎么办? 如果是javascript?我想我会定义一个参数来代表这个类型,像这样:

const T = number
function identity(arg: T): T { return arg; }
// 这样就约定了输入和输出都是number类型,输入输出保持一致
// TS中的泛型就是用来解决这样的问题的
TS的写法
function identity<T>(arg: T): T { return arg; }

这样规定后,T可以是任意类型,但是输入输出必须都是同一种类型,它和any不一样的地方就在于any无法保证前后的一致性,而泛型T则能够捕获入参T的类型,并且将这个类型设置为返回类型。

当T没有做任何类型声明的时候,T是可以是任意类型的,所以一些类型独有的特性只有在类型明确的时候才可以使用,比如:

function loggingIdentity<T>(arg: T): T { 
    console.log(arg.length); // Error: T doesn't have .length return arg; 
    // T 没有声明任何类型,它可能是number类型,number是没有长度的
}

明确类型:

function loggingIdentity<T>(arg: T[]): T[] {
    console.log(arg.length); // 声明了T的类型是数组,数组是有长度的。 
}

继续我们对TypeScript类型系统的探索,让我们深入了解类型别名(type)这一强大的特性,它可以让我们以几乎任何方式定义类型。不同于接口(interface),类型别名给了我们更多的自由度和能力去定义类型,但这也意味着我们需要更好地理解它以充分利用其潜力。

类型别名(Type Alias)

类型别名,顾名思义,就是给一种类型起一个新的名字。它用type关键字来创建,这个名字可以引用基本类型、联合类型、交叉类型,甚至是复杂的泛型类型。

1type Point = {
2    x: number;
3    y: number;
4};

上面的代码定义了一个Point类型,它有两个数字属性:xy。这与接口定义非常相似,但类型别名的真正力量在于它的多功能性。

type vs interface

既然typeinterface都可以用来定义类型,那么它们之间的区别是什么呢?

  • 扩展与合并interface可以通过声明合并来扩展,非常适合定义对象的形状。当你多次声明同一个interface时,TypeScript会自动将它们合并为一个。相比之下,type不支持声明合并,但它可以通过交叉类型来扩展。
  • 类型别名的使用场景type更适合定义联合类型、元组类型或其他你可以想到的复杂类型。
  • 扩展性:当你想要一个类型可以被拓展或实现时,interface是更好的选择。而type则适用于你需要使用到交叉类型或联合类型的情况。

在实际应用中,应该根据具体情况选择使用type还是interface。当你需要类型合并或者希望其他开发者在API中拓展你的类型定义时,interface是更合适。