Structural Types

Nominal v. Structural Type Checking

One of the most important concepts to grasp about TypeScript is that in TypeScript type checking is not nominal but structural.

In a nominal type system type compatibility of an object is being checked not based on its structure (its shape) but the basis of its class or prototype.

In a nominal type system an object value cannot be assigned to a variable, parameter or property when that object value is of a different class to the class declared for that variable, parameter or property irrespective of whether the object is compatible structurally.

C++, C#, Java, and Swift primarily use the nominal typing system.

On the other hand, in a structural type system an object value cannot be assigned to a variable, parameter, or property only when the object value differs structurally from the type declaration of that variable, parameter, or property, and classes are not taken into account.

TypeScript features structural type system and therefore the below is fully acceptable.

In a structural type system, only an object's structure and not its class is taken into account when checking type compatibility.

TypeScript is an example of a structural type system. Other examples of structurally typed languages are Haskell and Elm.

Literal Structural Types

A literal structural type is a structural type without a name assigned to it.

A literal structural type cannot be declared or exist by itself. It can only be used as:

  • a variable type annotation,

  • an object property type annotation,

  • a function parameter type annotation,

  • a function return type annotation, and

  • a named structural type assignment.

Named Structural Types

In TypeScript, a named structural type is declared using the keyword type appended with a name and with a literal structural type assigned to it.

A property type of a structural type can be a named type itself.

In the above example the address property type is specified using the named type Address and the major property type is specified using the literal type { name: string, department: string }.