代码之家  ›  专栏  ›  技术社区  ›  user1283776

接口和类型别名之间有语义上的区别吗?

  •  3
  • user1283776  · 技术社区  · 7 年前

    我可以用接口和类型别名做大部分相同的事情。

    类可以实现接口或类型别名

    interface Shape {
        area(): number;
    }
    
    type Perimeter = {
        perimeter(): number;
    }
    
    class Rectangle implements Shape, Perimeter {
    }
    

    interface A {
        a: string;
    }
    
    type B = {
        b: string
    }
    
    interface C extends B {
        c: string;
    }
    
    type D = A & {
        d: string;
    }
    

    接口和类型注释之间是否存在语义差异?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Robbie Milejczak Diego Felipe    7 年前

    接口可以扩展其他接口,也可以*实现类。接口还可以利用 declaration merging :

    type A = {
      a: string;
    }
    
    type A = { // <-- error: duplicate identifier A
      b: string;
    }
    
    interface A {
      a: string;
    }
    
    interface A { // <-- okay, A is { a: string, b: string } 
      b: string; 
    }
    

    编辑:已将扩展更改为*实现

    编辑2:交点与延伸不同。考虑以下事项:

    interface A {
      num: number;
      str: string; 
    }
    
    type B = A & { // <-- this is okay, but overwrites the num property type to number & string
      arr: any[];
      num: string;
    }
    
    interface C extends A { // <-- error: C incorrectly extends A
      num: string;
    }
    

    编辑3:对于某些人来说,另一个潜在的显著差异(虽然不一定是语义差异)是类型在工具提示中被枚举(至少在vscode中),而接口则不是。

        2
  •  1
  •   Paleo    7 年前

    两者之间存在技术差异 interface 和 type 那是 well-described here

    但是,对于以下情况: 和 两者都可以使用,没有任何语义差异。

    关于 继承与 打字稿中的交集

    在TypeScript中,接口之间的层次结构只是定义接口的一种方式。但一旦定义了它们,接口之间就没有真正的父子关系。例如:

    interface Named {
        name: string
    }
    interface Person extends Named {
        age: number
    }
    interface Animal {
        name: string
        age: number
    }
    

    在这里 Person 和 Animal

    function useNamed(named: Named) {
    }
    let p: Person = /* ... */
    let a: Animal = /* ... */
    useNamed(p) // OK
    useNamed(a) // also OK, because if 'Animal' is compatible with
                // `Named` then it is a `Named`
    

    这就是为什么同样的类型也可以使用 :

    type Engine = Named & {
        age: number
    }
    

    根据规范:

    交叉口类型 表示同时具有多个类型的值。交叉点类型的值 A. B 是一个 类型 A. 和类型 B TypeScript Specification

    我们的 Engine 类型既是一个 Named 另外一个定义是:它在语义上与接口继承相同。和 发动机 人 和 动物 .

    推荐文章