TypeScript 中的交叉类型与接口类型

3

以下是情景:

type Admin = {
    name : string,
    privileges : string[]
}
type Employee ={
    name : string,
    startDate : Date
}

type ElevatedEmployee = Admin & Employee;

const el : ElevatedEmployee ={ // all the properties must be implemented here else compiler will complain
    name : 'Max',
    privileges :['create server'],
    startDate : new Date()
}

我可以使用接口来实现相同的功能:

interface Admin {
    name : string,
    privileges : string[]
}

interface Employee {
     name : string,
    startDate : Date
}

interface Combined extends Admin, Employee { 
//this doesn't throw me a compilation error, even though i dont implement those properties here
}


什么是交叉类型和接口?何时使用哪个?
1个回答

9

1. 性能

根据TypeScript性能维基

接口创建一个单一的扁平化对象类型,检测属性冲突,通常解决这些冲突非常重要!另一方面,交集只是递归地合并属性,并且在某些情况下会产生never。接口显示的效果也更好,而类型别名到交集无法在其他交集中部分显示。接口之间的类型关系也被缓存,而交集类型则整体缓存。最后需要注意的是,在针对目标交集类型进行检查时,会在检查“有效”/“扁平化”类型之前先检查每个成分。

因此,建议使用接口/extends来扩展类型而不是创建交集类型,如果您担心TS性能问题,应考虑使用接口。

2. 接口与类型之间的微妙差别

types默认为索引,而interfaces则不是。这使得interfaces更加安全。请考虑以下示例:

type Admin = {
    name: string,
    privileges: string[]
}

type Employee = {
    name: string,
    startDate: Date
}

type CombinedType = Admin & Employee;

interface CombinedInterface extends Admin, Employee { }

const interfaceData: CombinedInterface = { name: '', privileges: [], startDate: new Date() }
const typeData: CombinedType = { name: '', privileges: [], startDate: new Date() }


const handleType = (obj: Record<string, unknown>) => {
    obj['name'] = 42 // unsafe
}


handleType(interfaceData) // error
handleType(typeData) // ok



请参考我的文章和这个答案了解更多背景信息。
正如您可能已经注意到的那样,handleType 几乎可以接受任何对象,并且能够以不安全的方式进行修改/改变它。但是,如果您有一个带有interface的对象,则无法将其传递给不安全的函数。
P.S. 在评估方面,类型和接口之间存在一些微妙的差异,请参见这里,但这与您的示例无关。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接