什么时候在TS中使用类型(Type)(而不是接口(Interface))
什么时候在TS中使用类型(Type)(而不是接口(Interface))
这个问题已经有答案了:
我无法确定何时,如果有的话,在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
?
编辑(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组件或其他内容)。使用"类型"定义,这种联合/交叉等的语言使得这种操作非常简单。
因此,逻辑仍然符合;接口表示水平行为,类型表示可垂直组合的定义。