什么时候在TS中使用类型(Type)(而不是接口(Interface))

20 浏览
0 Comments

什么时候在TS中使用类型(Type)(而不是接口(Interface))

这个问题已经有答案了:

TypeScript中的接口和类型的区别

我无法确定何时,如果有的话,在TypeScript中使用type代替interface进行变量定义。假设有以下两个:

type User = {
    id: string;
    name: string;
    type: string;
}
interface User {
    id: string;
    name: string;
    type: string;
}

我可以使用完全相同的方式定义变量const user: User = ...。然而,以下是我可以使用interface而不能使用type的所有操作:

// Extension:
interface AdminUser extends User {
    permissions: string[];
    role: string;
}
// Using in abstract method:
abstract class Home {
    abstract login(user: User): void;
}
class AdminHome extends Home {
    login(user: AdminUser) {
        ...
    }
}

仅举几例。

所以我的问题是:何时才需要使用 type

admin 更改状态以发布 2023年5月21日
0
0 Comments

编辑(2020年12月15日):在底部,我已经添加了关于TS中“类型”(或者另一种语言中等价的概念)的信息。

如果我没弄错的话,您可能不清楚接口和类型的用途有何区别。

从面向对象编程(OOP)的角度来看,接口是没有实现的,而类型是有实现的。因此,除非类型实现了接口,否则接口基本上是无用的。此外,类型只能扩展另一种类型,但它可以实现许多接口。

但这意味着什么...

假设您有一辆汽车和一个用户。这些是非常不同的类型,你不会立即认为它们在实际使用中是相同的。有人可能会说,“嗯,你应该创建ICar和IUser”。但实际上,这不是一种实际的接口使用方式。让用户实现ICar,或者ICar似乎只是做和Car一样的事情。对于查看代码的另一个程序员而言,有什么不同呢?

假设您想要它们都是"自我描述"的,并且您希望它们都以相同的方式提供信息。那么您将创建:

ISelfDescribable {
   getSelfDescription ( );
}

接下来,您将执行以下操作:

Car implements ISelfDescribable {
   getSelfDescription ( return "I am a car!" );
}
User implements ISelfDescribable {
  getSelfDescription ( return ...some other completely different way of getting the info... );
}

这些对象的数组将是(考虑如果没有接口,您将如何执行此操作):

Array

现在您(以及查看代码的任何其他开发人员)可以确定,该数组中的任何对象,无论具体类型如何,都实现了ISelfDesribable的"行为"。如果您认真思考,除非您正在实现它,否则根本不需要了解类型是什么,您只需要关心其行为即可。但是,您仍然需要该类型来实现该行为。

假设有一天,您希望这两个对象都是"可保险的"。它们都应该具有一个"设置保险政策"的方法。您可以创建 IInsurable { setInsurancePolicy ( policy : Policy ) }并在类型中实现它。现在您拥有既是ISelfDescribable,又是IInsurable的对象,并且您可以将这些对象的数组类型设置为任一对象类型。

因此,对我来说,当我理解到这一点时,我就豁然开朗: 类型(和类型层次结构)应着眼于具体事物。接口应关注可以在不同类型之间共享的行为。当然,这只是其中一部分,但至少可以让您了解为什么要选择接口或类型。它们在编程方面代表着不同的事物,即使它们在其他方面看起来相同。

(补充说明:像Scala这样的语言不会像这样思考接口。它们确实有"行为"的概念,但您也可以实现并重写它们。这可能对于这个特定问题来说是太过学术性的废话了,但是我必须杀死地牢里的所有怪物,而不仅仅是任务里的怪物。)

2020年12月15日:TypeScript:类型与接口。

为什么使用其中之一?这又涉及到您想要它代表什么以及您想要如何使用它。

"类型"是"I need a contract but it's not a behavior definition like an interface"的答案。

这使您可以在语义上保持差异。这是一个接口,因为它定义了水平行为。这是一种类型,因为它定义了...一种类型。

但更进一步地说,类型在某种程度上比接口更适合函数友好,因为您可以组合和交叉类型。例如,在React中,我听说过“永远不要使用接口,因为它们远不如类型可组合”。

假设您有两个服务调用,想要为有效载荷定义合同。接口?不是...那是为了水平行为。但是,"类型"是的,它对有效载荷进行了类型定义,但没有在语义上定义行为。

而且,假设您遇到了经常出现的任务,即需要将两个有效载荷类型的定义合并成一个(用于UI组件或其他内容)。使用"类型"定义,这种联合/交叉等的语言使得这种操作非常简单。

因此,逻辑仍然符合;接口表示水平行为,类型表示可垂直组合的定义。

0