TypeScript: interfaces versus typen

Wat is het verschil tussen deze uitspraken (interface vs type)?

interface X {
    a: number
    b: string
}
type X = {
    a: number
    b: string
};

Antwoord 1, autoriteit 100%

Update maart 2021: het nieuwere TypeScript-handboek heeft een sectie Interfaces vs. Type Aliaseswat de verschillen verklaart.


Origineel antwoord (2016)

Volgens de (nu gearchiveerd) TypeScript-taalspecificatie :

In tegenstelling tot een interfacedeclaratie, die altijd een benoemd objecttype introduceert, kan een type-aliasdeclaratieeen naam introduceren voor elk type type, inclusief primitieve, union- en intersectietypen.

De specificatie vermeldt verder:

Interfacetypenhebben veel overeenkomsten met het typen van aliassen voor het objecttype
letterlijken, maar aangezien interfacetypes meer mogelijkheden bieden, zijn ze
over het algemeen liever aliassen typen. Bijvoorbeeld het interfacetype

interface Point {
    x: number;
    y: number;
}

kan worden geschreven als het type alias

type Point = {
    x: number;
    y: number;
};

Als u dit echter doet, gaan de volgende mogelijkheden verloren:

  • Een interface kan worden genoemd in een uitreide of implementaire clausule, maar een type alias voor een letterlijk objecttype kan niet niet langer waar sinds TS 2.7.
  • Een interface kan meerdere samengevoegde aangiften , maar een type alias Voor een lettertype kan letterlijk niet.

2, Autoriteit 133%

2019 update


De huidige antwoorden en de officiële documentatie zijn verouderd. En voor die nieuwe tot typoscoop is de gebruikte terminologie niet duidelijk zonder voorbeelden. Hieronder staat een lijst met actuele verschillen.

1. Objecten / Functies

Beide kunnen worden gebruikt om de vorm van een object of een functiesignatuur te beschrijven. Maar de syntaxis verschilt.

interface

interface Point {
  x: number;
  y: number;
}
interface SetPoint {
  (x: number, y: number): void;
}

Type Alias ​​

type Point = {
  x: number;
  y: number;
};
type SetPoint = (x: number, y: number) => void;

2. Andere typen

In tegenstelling tot een interface, kan het type alias ook worden gebruikt voor andere typen zoals primitieven, vakbonden en tuples.

// primitive
type Name = string;
// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };
// union
type PartialPoint = PartialPointX | PartialPointY;
// tuple
type Data = [number, string];

3. Uitbreiden

Beide kunnen worden uitgebreid, maar nogmaals, de syntaxis verschilt. Houd er bovendien rekening mee dat een interface en type-alias elkaar niet uitsluiten. Een interface kan een type-alias uitbreiden en vice versa.

Interface breidt interface uit

interface PartialPointX { x: number; }
interface Point extends PartialPointX { y: number; }

Type alias breidt type alias uit

type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };

Interface breidt type-alias uit

type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }

Type alias breidt interface uit

interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };

4. Werktuigen

Een klasse kan een interface implementeren of een alias typen, beide op exact dezelfde manier. Merk echter op dat een klasse en interface worden beschouwd als statische blauwdrukken. Daarom kunnen ze geen type-alias implementeren/uitbreiden die een union-type noemt.

interface Point {
  x: number;
  y: number;
}
class SomePoint implements Point {
  x = 1;
  y = 2;
}
type Point2 = {
  x: number;
  y: number;
};
class SomePoint2 implements Point2 {
  x = 1;
  y = 2;
}
type PartialPoint = { x: number; } | { y: number; };
// FIXME: can not implement a union type
class SomePartialPoint implements PartialPoint {
  x = 1;
  y = 2;
}

5. Aangifte samenvoegen

In tegenstelling tot een type alias, kan een interface meerdere keren worden gedefinieerd en wordt deze behandeld als een enkele interface (waarbij leden van alle declaraties worden samengevoegd).

// These two declarations become:
// interface Point { x: number; y: number; }
interface Point { x: number; }
interface Point { y: number; }
const point: Point = { x: 1, y: 2 };

Antwoord 3, autoriteit 17%

Vanaf TypeScript 3.2 (november 2018) is het volgende waar:


Antwoord 4, autoriteit 9%


Wanneer gebruik je type?


Algemene transformaties

Gebruik het typewanneer u meerdere typen omzet in één generiek type.

Voorbeeld:

type Nullable<T> = T | null | undefined
type NonNull<T> = T extends (null | undefined) ? never : T

Alias typen

We kunnen het typegebruiken voor het maken van aliassen voor lange of gecompliceerde typen die moeilijk te lezen zijn en ook onhandig om steeds opnieuw te typen.

Voorbeeld:

type Primitive = number | string | boolean | null | undefined

Het maken van een alias als deze maakt de code beknopter en leesbaarder.


Type vastleggen

Gebruik het typeom het type van een object vast te leggen wanneer het type onbekend is.

Voorbeeld:

const orange = { color: "Orange", vitamin: "C"}
type Fruit = typeof orange
let apple: Fruit

Hier krijgen we de onbekende soort orange, noem het een Fruiten gebruik de Fruitom een ​​nieuw type-safe te creëren object apple.


Wanneer gebruikt u interface?


polymorfisme

Een interfaceis een opdracht om een ​​vorm van de gegevens uitvoeren. Gebruik de interface om duidelijk te maken dat het de bedoeling is om te worden uitgevoerd en gebruikt als een contract over hoe het object zal worden gebruikt.

Voorbeeld:

interface Bird {
    size: number
    fly(): void
    sleep(): void
}
class Hummingbird implements Bird { ... }
class Bellbird implements Bird { ... }

Hoewel u de typekan gebruiken om dit te bereiken, de Typescript wordt meer gezien als een object-georiënteerde taal en de interfaceheeft een speciale plaats in objectgeoriënteerde talen. Het is makkelijker om de code te lezen interfacewanneer u werkt in een team omgeving of bij te dragen aan de open source gemeenschap. Het is gemakkelijk op de nieuwe programmeurs uit andere objectgeoriënteerde talen ook.

De officiële Typescript documentatie ook zegt:

… we raden het gebruik van een interfaceop een typealias wanneer dat mogelijk is.

Dit suggereert ook dat de typeis meer bedoeld voor het creëren van het type aliassen dan het maken van de types zelf.


Verklaring Samenvoegen

U kunt de functie Verklaring samenvoegen van de interfacegebruiken voor het toevoegen van nieuwe eigenschappen en methoden in een reeds gedeclareerde interface. Dit is handig voor de omgevingstype-verklaringen van bibliotheken van derden. Wanneer sommige aangiften ontbreken voor een bibliotheek van derden, kunt u de interface opnieuw met dezelfde naam verklaren en nieuwe eigenschappen en methoden toevoegen.

Voorbeeld:

We kunnen de bovenstaande Birdinterface uitbreiden met nieuwe aangiften.

interface Bird {
    color: string
    eat(): void
}

Dat is het! Het is gemakkelijker om te onthouden wanneer u moet gebruiken wat dan verdwaalt in subtiele verschillen tussen de twee.


Antwoord 5, autoriteit 3%

https://www.typescriptlang.org/docs/handbook/advanced- typen.html

Een verschil is dat interfaces een nieuwe naam creëren die overal wordt gebruikt. Type aliassen maken geen nieuwe naam aan — foutberichten gebruiken bijvoorbeeld niet de aliasnaam.


Antwoord 6, autoriteit 2%

Voorbeelden met typen:

// maak een boomstructuur voor een object. Je kunt niet hetzelfde doen met de interface vanwege het ontbreken van een kruising (&)

type Tree<T> = T & { parent: Tree<T> };

// typ om een variabele te beperken tot het toewijzen van slechts een paar waarden. Interfaces hebben geen union (|)

type Choise = "A" | "B" | "C";

// dankzij typen kun je NonNullable type declareren dankzij een voorwaardelijk mechanisme.

type NonNullable<T> = T extends null | undefined ? never : T;

Voorbeelden met interface:

// je kunt de interface voor OOP gebruiken en ‘implements’ gebruiken om het object/klasse-skelet te definiëren

interface IUser {
    user: string;
    password: string;
    login: (user: string, password: string) => boolean;
}
class User implements IUser {
    user = "user1"
    password = "password1"
    login(user: string, password: string) {
        return (user == user && password == password)
    }
}

// je kunt interfaces uitbreiden met andere interfaces

   interface IMyObject {
        label: string,
    }
    interface IMyObjectWithSize extends IMyObject{
        size?: number
    }

Antwoord 7

Andere antwoorden zijn geweldig! Weinig andere dingen die typekunnen doen, maar interfaceniet

U kunt unie gebruiken in type

type Name = string | { FullName: string };
const myName = "Jon"; // works fine
const myFullName: Name = {
  FullName: "Jon Doe", //also works fine
};

Itereren over unie-eigenschappen in type

type Keys = "firstName" | "lastName";
type Name = {
  [key in Keys]: string;
};
const myName: Name = {
  firstName: "jon",
  lastName: "doe",
};

Intersection in type (echter ook ondersteund in Interface with extends)

type Name = {
  firstName: string;
  lastName: string;
};
type Address = {
  city: string;
};
const person: Name & Address = {
  firstName: "jon",
  lastName: "doe",
  city: "scranton",
};

Ook niet dat typelater werd geïntroduceerd in vergelijking met interfaceen volgens de laatste release van TS kan type*bijna alles doen wat interfacekan en nog veel meer!


*behalve Declaration merging(persoonlijke mening: het is goed dat het niet wordt ondersteund in type omdat dit kan leiden tot inconsistentie in de code)


Antwoord 8

Typescript Handbook geeft het antwoord: Het sleutelonderdeel is dat een type niet opnieuw kan worden geopend om nieuwe eigenschappen vs een interface toe te voegen die altijd uitbreidbaar is.

Link: HTPS: // www. typescriptLang.org/docs/handbook/advanced-types.html#interfaces-vs-type-aliases


9

Naast de briljante antwoorden die al zijn verstrekt, zijn er merkbare verschillen als het gaat om die zich uitstrekt typen vs-interfaces. Ik ben onlangs een paar gevallen tegengekomen waar een interface de taak niet kan doen:

  1. kan dat niet uitbreiding van een type type met behulp van een interface
  2. kan de generieke interface niet verlengen

10

Interfaces VS-typen

Interfaces en typen worden gebruikt om de soorten objecten en primitieven te beschrijven. Beide interfaces en typen kunnen vaak door elkaar worden gebruikt en bieden vaak soortgelijke functionaliteit. Meestal is het de keuze van de programmeur om hun eigen voorkeur te kiezen.

Interfaces kunnen echter alleen objecten en klassen beschrijven die deze objecten maken. Daarom moeten typen worden gebruikt om de primitieven zoals strings en cijfers te beschrijven.

Hier is een voorbeeld van 2 verschillen tussen interfaces en typen:

// 1. Declaration merging (interface only)
// This is an extern dependency which we import an object of
interface externDependency { x: number, y: number; }
// When we import it, we might want to extend the interface, e.g. z:number
// We can use declaration merging to define the interface multiple times
// The declarations will be merged and become a single interface
interface externDependency { z: number; }
const dependency: externDependency = {x:1, y:2, z:3}
// 2. union types with primitives (type only)
type foo = {x:number}
type bar = { y: number }
type baz = string | boolean;
type foobarbaz = foo | bar | baz; // either foo, bar, or baz type
// instances of type foobarbaz can be objects (foo, bar) or primitives (baz)
const instance1: foobarbaz = {y:1} 
const instance2: foobarbaz = {x:1} 
const instance3: foobarbaz = true 

Antwoord 11

Hier is nog een verschil. Ik zal… een biertje voor je kopen als je de redenering of reden van deze gang van zaken kunt uitleggen:

enum Foo { a = 'a', b = 'b' }
type TFoo = {
  [k in Foo]: boolean;
}
const foo1: TFoo = { a: true, b: false} // good
// const foo2: TFoo = { a: true }       // bad: missing b
// const foo3: TFoo = { a: true, b: 0}  // bad: b is not a boolean
// So type does roughly what I'd expect and want
interface IFoo {
//  [k in Foo]: boolean;
/*
  Uncommenting the above line gives the following errors:
  A computed property name in an interface must refer to an expression whose type is a      
    literal type or a 'unique symbol' type.
  A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
  Cannot find name 'k'.
*/
}
// ???

Dit soort zorgt ervoor dat ik de hel met interfaceswil zeggen, tenzij ik opzettelijk een OOP-ontwerppatroon implementeer, of samenvoeging nodig heb zoals hierboven beschreven (wat ik nooit zou doen tenzij ik een zeergoede reden voor).


Antwoord 12

Verschil in indexering.

interface MyInterface {
  foobar: string;
}
type MyType = {
  foobar: string;
}
const exampleInterface: MyInterface = { foobar: 'hello world' };
const exampleType: MyType = { foobar: 'hello world' };
let record: Record<string, string> = {};
record = exampleType;      // Compiles
record = exampleInterface; // Index signature is missing

Dus overweeg dan dit voorbeeld, als u wilt indexeren van uw object

Neem een ​​kijkje op deze vraag

Verschil in evaluatie

De resultaten type ExtendFirstals FirstLevelTypegrensvlak

/**
 * When FirstLevelType is interface 
 */
interface FirstLevelType<A, Z> {
    _: "typeCheck";
};
type TestWrapperType<T, U> = FirstLevelType<T, U>;
const a: TestWrapperType<{ cat: string }, { dog: number }> = {
  _: "typeCheck",
};
// {  cat: string; }
type ExtendFirst = typeof a extends FirstLevelType<infer T, infer _>
    ? T
    : "not extended";

De resultaten type ExtendFirstals FirstLevelTypeis een type:


/**
 * When FirstLevelType is type
 */
type FirstLevelType<A, Z>= {
    _: "typeCheck";
};
type TestWrapperType<T, U> = FirstLevelType<T, U>;
const a: TestWrapperType<{ cat: string }, { dog: number }> = {
  _: "typeCheck",
};
// unknown
type ExtendFirst = typeof a extends FirstLevelType<infer T, infer _>
    ? T
    : "not extended";

13

Als het gaat om compilatiesnelheid, presteren gecomponeerde interfaces beter dan type kruispunten:

[…] -interfaces maken een enkel plat objecttype dat vastgoedconflicten detecteert. Dit staat in contrast met kruispuntsoorten, waarbij elk bestanddeel wordt gecontroleerd voordat ze worden gecontroleerd tegen het effectieve type. Type-relaties tussen interfaces zijn ook in de cache, in tegenstelling tot kruispunten.

Bron: https://github.com/microsoft / TypenScript / Wiki / Performance # Prefer-interfaces-over-kruispunten


14

In typescript, “Interface” wordt aanbevolen via “Type”.

  • “Type” wordt gebruikt voor het maken van typealiassen.

    type Data=string
    

In plaats daarvan te gebruiken, kunt u “gegevens”

gebruiken

const name:string="Yilmaz"
const name:Data="Yilmaz"

Aliasen zijn erg handig, vooral als je met generieke typen werkt.

U kunt dit niet doen met “interface”.

  • U kunt interfaces samenvoegen, maar geen typen.

    interface Persoon {
    naam: tekenreeks;
    }

     interface Person {
        age: number;
      }
      const me: Person = {
        name: "Yilmaz Bingol",
        age: 30
      };
    
  • gebruikers van functioneel programmeren gebruiken “type”, gebruikers van objectgeoriënteerd programmeren kiezen voor “interface”

  • U kunt geen berekende of berekende eigenschappen hebben op interfaces, maar in type.

    type Volledige naam = “naam” | “achternaam”

     type  Person= {
         [key in Keys]: string
      }
      const me: Person = {
         firstname: "Yilmaz",
         lastname: "Bingol"
      }
    

Antwoord 15

Nou, ‘typescriptlang’ lijkt aan te bevelen om waar mogelijk interfaces te gebruiken boven typen.

Interface versus type-alias


Antwoord 16

ze verschillen qua semantiek.

een interface is een normaal syntaxiselement in een TS-systeem. het is een native onderdeel van de TS-syntaxis.

terwijl een type-alias een syntaxissuiker is. het is een soort metaprogrammering.


Antwoord 17

de documentatie heeft uitgelegd

  • Een verschil is dat interfaces een nieuwe naam creëren die overal wordt gebruikt. Type-aliassen maken geen nieuwe naam aan – foutberichten gebruiken bijvoorbeeld niet de aliasnaam. In oudere versies van TypeScript kunnen type-aliassen niet worden uitgebreid of geïmplementeerd (noch kunnen ze andere typen uitbreiden/implementeren). Vanaf versie 2.7 kunnen type-aliassen worden uitgebreid door een nieuw kruispunttype te maken
  • Aan de andere kant, als je een vorm niet kunt uitdrukken met een interface en je moet een union- of tuple-type gebruiken, zijn type-aliassen meestal de beste keuze.

Interfaces versus typealiassen

Other episodes