Skip to main content

Type comparison

A type A is called a subtype of a type B if any valid value for A is a valid value for B. This means that B has a broader range of values.

The "is subtype of" relation between types is partial order relation equivalent to the "is subset of" relation (set inclusion) if types were defined as a set of values. Note that the reflexivity of partial orders translates to "for all type A, A is a subtype of A".

This type comparison is required for the validation of from parent injections.

Semantics​

In this section A and B denote types, U and V denote lists of types.

If A is a subtype of B, then A and B are either both scalar types or both non-scalar types.

Scalar types​

  1. If A is a scalar type and A is a subtype of B then B is a scalar type or a union type with at least one variant that is a supertype of A.

    Note that this is stricter than it should be because we currently only check individually on each union variant.

  2. If A is a subtype of B and B is a scalar type then A is a scalar type of a union type in which any variant is a subtype of B.

  3. Suppose that A and B are scalar types.

    Then A is subtype of B if and only if the following conditions hold:

    • A and B are the same type or A is a t.integer() and B is a t.float();

    • Type constraints defined on B are all defined on A and satisfy:

      TypeType ConstraintCondition
      t.integer(), t.float()minA.min >= B.min
      t.integer(), t.float()x_minA.x_min >= B.x_min
      t.integer(), t.float()maxA.max <= B.max
      t.integer(), t.float()x_maxA.x_max <= B.x_max
      t.integer(), t.float()multiple_ofA.multiple_of is a multiple of B.multiple_of
      t.string()minA.min >= B.min
      t.string()maxA.max <= B.max
      t.string()patternA.pattern == B.pattern1
      t.string()formatA.format == B.format
      t.file()minA.min >= B.min
      t.file()maxA.max <= B.max
      t.file()allowA.allow is a subset of B.allow

      Note that type constraints defined on A are not required to be defined on B.

    • If B is an enum, then A is an enum and all enumeration values defined for A are defined for B.

Optionals​

  1. A is a subtype of t.optional(B) if and only if A is subtype of B.

  2. t.optional(A) is a subtype of t.optional(B) if and only if A is a subtype of B.

  3. If B is not an optional type, then t.optional(A) is not a subtype of B.

Lists​

  1. Suppose that A and B are non-optional types and A is a subtype of B. If A is a list then B is a list and vice-versa.

  2. Let X a list type whose item type is A, and Y a list type whose item type is B. X is a subtype of Y if and only if

    • A is a subtype of B,
    • Type constraints defined on X are all defined on Y and satisfy:
      Type constraintCondition
      minX.min >= Y.min
      maxX.max <= Y.max
      unique_itemsX.unique_items == Y.unique_items

Note that the type constraints defined on X are not required to be defined on Y.

Objects: t.struct()​

  1. Suppose that A and B are non-optional types and A is a subtype of B. If A is an object type then B is an object type, and vice-versa.

  2. If A and B are object types, then A is a subtype of B if and only if

    • All field key defined in A is defined in B,
    • For all field defined in B with key K, either the field is optional on B or A has a field with key K whose type is a subtype of the one in B;
    • Type constraints defined on B are all defined on A and satisfy:
      Type constraintCondition
      minA.min >= B.min
      maxA.max <= B.max

Unions: t.union() and t.either()​

  1. If A is a type and V a list of types then A is a subtype of t.union(V) if and only if there is a type B in V such that A is a subtype of B.

  2. If A is a type and V a list of types then A is a subtype of t.either(V) if and only if there is a unique type B in V such that A is a subtype of B.

  3. If U is a list of types and B a type then

    • t.union(U) is a subtype of B if and only if each type A in U is a subtype of B;
    • t.either(U) is a subtype of B if and only if each type A in U is a subtype of B.

Examples​

You can find examples of type comparison in the type comparison test suite.

Footnotes​

  1. The patterns are required to be exactly the same because we currently do not have any other comparison semantic for regular expressions. ↩