These differ only in that assignment extends subtype compatibility with rules to allow assignment to and from any, and to and from enum with corresponding numeric values.ĭifferent places in the language use one of the two compatibility mechanisms, depending on the situation.įor practical purposes, type compatibility is dictated by assignment compatibility, even in the cases of the implements and extends clauses. In TypeScript, there are two kinds of compatibility: subtype and assignment. So far, we’ve used “compatible”, which is not a term defined in the language spec. Identity = reverse // OK, because (x: any) => any matches (y: any) => any Advanced Topics Subtype vs Assignment The motivating example is the common pattern of a function that takes a callback and invokes it with some predictable (to the programmer) but unknown (to the type system) number of arguments: This is unsound from a type system perspective, but from a runtime point of view the idea of an optional parameter is generally not well-enforced since passing undefined in that position is equivalent for most functions.
When a function has a rest parameter, it is treated as if it were an infinite series of optional parameters.
When comparing functions for compatibility, optional and required parameters are interchangeable.Įxtra optional parameters of the source type are not an error, and optional parameters of the target type without corresponding parameters in the source type are not an error. You can have TypeScript raise errors when this happens via the compiler flag strictFunctionTypes.
For example consider the following code involving an interface named Pet which has a name property: The basic rule for TypeScript’s structural type system is that x is compatible with y if y has at least the same members as x. The places where TypeScript allows unsound behavior were carefully considered, and throughout this document we’ll explain where these happen and the motivating scenarios behind them. When a type system has this property, it is said to not be “sound”. TypeScript’s type system allows certain operations that can’t be known at compile-time to be safe.
TypeScript’s structural type system was designed based on how JavaScript code is typically written.īecause JavaScript widely uses anonymous objects like function expressions and object literals, it’s much more natural to represent the kinds of relationships found in JavaScript libraries with a structural type system instead of a nominal one. In nominally-typed languages like C# or Java, the equivalent code would be an error because the Dog class does not explicitly describe itself as being an implementer of the Pet interface.