# Intersection type

> Mediated Wiki article. Canonical URL: https://mediated.wiki/source/Intersection_type
> Markdown URL: https://mediated.wiki/source/Intersection_type.md
> Source: https://en.wikipedia.org/wiki/Intersection_type
> Source revision: 1336897094
> License: Creative Commons Attribution-ShareAlike 4.0 International (https://creativecommons.org/licenses/by-sa/4.0/)

Data type for values having two types

Type systems General concepts Type safety Strong vs. weak typing Major categories Static vs. dynamic Manifest vs. inferred Nominal vs. structural Duck typing Minor categories Abstract Dependent Flow-sensitive Gradual Intersection Latent Refinement Substructural Unique Session v t e

In [type theory](/source/Type_theory), an **intersection type** can be allocated to values that can be assigned both the type σ {\displaystyle \sigma } and the type τ {\displaystyle \tau } . This value can be given the intersection type σ ∩ τ {\displaystyle \sigma \cap \tau } in an [intersection type system](/source/Intersection_type_system).[1] Generally, if the ranges of values of two types overlap, then a value belonging to the *intersection* of the two ranges can be assigned the *intersection type* of these two types. Such a value can be safely passed as argument to functions expecting *either* of the two types. For example, in [Java](/source/Java_(programming_language)) the class Boolean implements both the Serializable and the Comparable interfaces. Therefore, an object of type Boolean can be safely passed to functions expecting an argument of type Serializable and to functions expecting an argument of type Comparable.

Intersection types are [composite data types](/source/Composite_data_type). Similar to [product types](/source/Product_type), they are used to assign several types to an object. However, product types are assigned to [tuples](/source/Tuple), so that each tuple element is assigned a particular product type component. In comparison, underlying objects of intersection types are not necessarily composite. A restricted form of intersection types are [refinement types](/source/Refinement_type).

Intersection types are useful for describing [overloaded functions](/source/Function_overloading).[2] For example, if number => number is the type of function taking a number as an argument and returning a number, and string => string is the type of function taking a string as an argument and returning a string, then the intersection of these two types can be used to describe (overloaded) functions that do one or the other, based on what type of input they are given.

Contemporary programming languages, including [Ceylon](/source/Ceylon_(programming_language)), Flow, [Java](/source/Java_(programming_language)), [Scala](/source/Scala_(programming_language)), [TypeScript](/source/Microsoft_TypeScript), and [Whiley](/source/Whiley_(programming_language)) (see [comparison of languages with intersection types](#Comparison_of_languages_with_intersection_types)), use intersection types to combine interface specifications and to express [ad hoc polymorphism](/source/Ad_hoc_polymorphism). Complementing [parametric polymorphism](/source/Parametric_polymorphism), intersection types may be used to avoid class hierarchy pollution from [cross-cutting concerns](/source/Cross-cutting_concern) and reduce [boilerplate code](/source/Boilerplate_code), as shown in the [TypeScript example](#TypeScript_example) below.

The [type theoretic](/source/Type_theory) study of intersection types is referred to as the [intersection type discipline](/source/Intersection_type_discipline).[3] Remarkably, program termination can be precisely characterized using intersection types.[4] Consequently, [type inference](/source/Type_inference) for infinite-intersection types is [undecidable](/source/Undecidable_problem), but it is decidable for all finite rank intersection types.[5]

## TypeScript example

[TypeScript](/source/TypeScript) supports intersection types,[6] improving expressiveness of the type system and reducing potential class hierarchy size, demonstrated as follows.

The following program code defines the classes Chicken, Cow, and RandomNumberGenerator that each have a method produce returning an object of either type Egg, Milk, or number. Additionally, the functions eatEgg and drinkMilk require arguments of type Egg and Milk, respectively.

class Egg {
    private kind: "Egg";
}

class Milk {
    private kind: "Milk";
}

// "Produces" a product
interface Producer<T> {
    produce(): T;
}

// produces eggs
class Chicken implements Producer<Egg> {
    produce(): Egg {
        return new Egg();
    }
}

// produces milk
class Cow implements Producer<Milk> {
    produce(): Milk {
        return new Milk();
    }
}

// produces a random number
class RandomNumberGenerator implements Producer<number> {
    produce(): number {
        return Math.random();
    }
}

// requires an egg
function eatEgg(egg: Egg): string {
    return "I ate an egg.";
}

// requires milk
function drinkMilk(milk: Milk): string {
    return "I drank some milk.";
}

The following program code defines the [ad hoc polymorphic](/source/Ad_hoc_polymorphism) function animalToFood that invokes the member function produce of the given object animal. The function animalToFood has *two* type annotations, namely ((_: Chicken) => Egg) and ((_: Cow) => Milk), connected via the intersection type constructor &. Specifically, animalToFood when applied to an argument of type Chicken returns an object of type Egg, and when applied to an argument of type Cow returns an object of type Milk. Ideally, animalToFood should not be applicable to any object having (possibly by chance) a produce method.

// given a chicken, produces an egg; given a cow, produces milk
const animalToFood: ((animal: Chicken) => Egg) & ((animal: Cow) => Milk) = (animal: any) => {
    return animal.produce();
};

Finally, the following program code demonstrates [type safe](/source/Type_safety) use of the above definitions.

let chicken: Chicken = new Chicken();
let cow: Cow = new Cow();
let randomNumberGenerator: RandomNumberGenerator = new RandomNumberGenerator();

console.log(chicken.produce()); // Egg { }
console.log(cow.produce()); // Milk { }
console.log(randomNumberGenerator.produce()); // 0.2626353555444987

console.log(animalToFood(chicken)); // Egg { }
console.log(animalToFood(cow)); // Milk { }
// console.log(animalToFood(randomNumberGenerator)); // ERROR: Argument of type 'RandomNumberGenerator' is not assignable to parameter of type 'Cow'

console.log(eatEgg(animalToFood(chicken))); // I ate an egg.
// console.log(eatEgg(animalToFood(cow))); // ERROR: Argument of type 'Milk' is not assignable to parameter of type 'Egg'
console.log(drinkMilk(animalToFood(cow))); // I drank some milk.
// console.log(drinkMilk(animalToFood(chicken))); // ERROR: Argument of type 'Egg' is not assignable to parameter of type 'Milk'

The above program code has the following properties:

- Lines 1–3 create objects chicken, cow, and randomNumberGenerator of their respective type.

- Lines 5–7 print for the previously created objects the respective results (provided as comments) when invoking produce.

- Line 9 (resp. 10) demonstrates type safe use of the method animalToFood applied to chicken (resp. cow).

- Line 11, if uncommented, would result in a type error at compile time. Although the *implementation* of animalToFood could invoke the produce method of randomNumberGenerator, the *type annotation* of animalToFood disallows it. This is in accordance with the intended meaning of animalToFood.

- Line 13 (resp. 15) demonstrates that applying animalToFood to chicken (resp. cow) results in an object of type Egg (resp. Milk).

- Line 14 (resp. 16) demonstrates that applying animalToFood to cow (resp. chicken) does not result in an object of type Egg (resp. Milk). Therefore, if uncommented, line 14 (resp. 16) would result in a type error at compile time.

### Comparison to inheritance

The above minimalist example can be realized using [inheritance](/source/Inheritance_(object-oriented_programming)), for instance by deriving the classes Chicken and Cow from a base class Animal. However, in a larger setting, this could be disadvantageous. Introducing new classes into a class hierarchy is not necessarily justified for [cross-cutting concerns](/source/Cross-cutting_concern), or maybe outright impossible, for example when using an external library. Imaginably, the above example could be extended with the following classes:

- a class Horse that does not have a produce method;

- a class Sheep that has a produce method returning Wool;

- a class Pig that has a produce method, which can be used only once, returning Meat.

This may require additional classes (or interfaces) specifying whether a produce method is available, whether the produce method returns food, and whether the produce method can be used repeatedly. Overall, this may pollute the class hierarchy.

### Comparison to duck typing

The above minimalist example already shows that [duck typing](/source/Duck_typing) is less suited to realize the given scenario. While the class RandomNumberGenerator contains a produce method, the object randomNumberGenerator should not be a valid argument for animalToFood. The above example can be realized using duck typing, for instance by introducing a new field argumentForAnimalToFood to the classes Chicken and Cow signifying that objects of corresponding type are valid arguments for animalToFood. However, this would not only increase the size of the respective classes (especially with the introduction of more methods similar to animalToFood), but is also a non-local approach with respect to animalToFood.

### Comparison to function overloading

The above example can be realized using [function overloading](/source/Function_overloading), for instance by implementing two methods animalToFood(animal: Chicken): Egg and animalToFood(animal: Cow): Milk. In TypeScript, such a solution is almost identical to the provided example. Other programming languages, such as [Java](/source/Java_(programming_language)), require distinct implementations of the overloaded method. This may lead to either [code duplication](/source/Code_duplication) or [boilerplate code](/source/Boilerplate_code).

### Comparison to the visitor pattern

The above example can be realized using the [visitor pattern](/source/Visitor_pattern). It would require each animal class to implement an accept method accepting an object implementing the interface AnimalVisitor (adding non-local [boilerplate code](/source/Boilerplate_code)). The function animalToFood would be realized as the visit method of an implementation of AnimalVisitor. Unfortunately, the connection between the input type (Chicken or Cow) and the result type (Egg or Milk) would be difficult to represent.

### Comparison with parametric polymorphism

[Parametric polymorphism](/source/Parametric_polymorphism) is conceptually equivalent to infinite intersection types.[7]

Intersection types have been promoted as being "compositional" in contrast with the [let-bound polymorphism](/source/Hindley%E2%80%93Milner_type_system) of ML (a restricted form of parametric polymorphism) because intersection types have [principal typings](/source/Principal_type) while ML's type system does not (not to be confused with principal types, which ML does enjoy). The lack of principal typings in ML translates into the need to evaluate some expressions before others in an ML program; essentially resulting in a data dependency at type-inference level in ML, in particular in let expressions.[8] Consequently, intersection types have been proposed as a way to improve [incremental compilation](/source/Incremental_compilation)[9] and/or [gradual typing](/source/Gradual_typing).[10]

On the other hand, intersection types have been criticized for not being compositional in another sense, namely that in a putative system that uses only intersection types but has no parametric polymorphism, inferred types may depend on the local features of a module, which may compose badly with other modules unless whole program compilation happens at source level. As a trivial example, an [identity function](/source/Identity_function) that is exposed through a public interface, e.g. exported by a module, ideally is parametrically polymorphic, so that it can be used with future types that the writer (of that function) doesn't yet know about. However, in a system that only has intersection types, such a function would be inferred to intersect at best over types existing when it is compiled.[11]

### Limitations

On the one hand, intersection types *can* be used to locally annotate different types to a function without introducing new classes (or interfaces) to the class hierarchy. On the other hand, this approach *requires* all possible argument types and result types to be specified explicitly. If the behavior of a function can be specified precisely by either a unified interface, parametric polymorphism, or [duck typing](/source/Duck_typing), then the verbose nature of intersection types is unfavorable. Therefore, intersection types should be considered complementary to existing specification methods.

## Dependent intersection type

A **dependent intersection type**, denoted ( x : σ ) ∩ τ {\displaystyle (x:\sigma )\cap \tau } , is a [dependent type](/source/Dependent_type) in which the type τ {\displaystyle \tau } may depend on the term variable x {\displaystyle x} .[12] In particular, if a term M {\displaystyle M} has the dependent intersection type ( x : σ ) ∩ τ {\displaystyle (x:\sigma )\cap \tau } , then the term M {\displaystyle M} has *both* the type σ {\displaystyle \sigma } and the type τ [ x := M ] {\displaystyle \tau [x:=M]} , where τ [ x := M ] {\displaystyle \tau [x:=M]} is the type which results from replacing all occurrences of the term variable x {\displaystyle x} in τ {\displaystyle \tau } by the term M {\displaystyle M} .

### Scala example

[Scala](/source/Scala_(programming_language)) supports type declarations [13] as object members. This allows a type of an object member to depend on the value of another member, which is called a *path-dependent type*.[14] For example, the following program text defines a Scala trait Witness, which can be used to implement the [singleton pattern](/source/Singleton_pattern).[15]

trait Witness {
  type T
  val value: T {}
}

The above trait Witness declares the member T, which can be assigned a *type* as its value, and the member value, which can be assigned a value of type T. The following program text defines an object booleanWitness as instance of the above trait Witness. The object booleanWitness defines the type T as Boolean and the value value as true. For example, executing System.out.println(booleanWitness.value) prints true on the console.

object booleanWitness extends Witness {
  type T = Boolean
  val value = true
}

Let ⟨ x : σ ⟩ {\displaystyle \langle {\textsf {x}}:\sigma \rangle } be the type (specifically, a [record type](/source/Record_(computer_science))) of objects having the member x {\displaystyle {\textsf {x}}} of type σ {\displaystyle \sigma } . In the above example, the object booleanWitness can be assigned the dependent intersection type ( x : ⟨ T : Type ⟩ ) ∩ ⟨ value : x . T ⟩ {\displaystyle (x:\langle {\textsf {T}}:{\text{Type}}\rangle )\cap \langle {\textsf {value}}:x.{\textsf {T}}\rangle } . The reasoning is as follows. The object booleanWitness has the member T that is assigned the type Boolean as its value. Since Boolean is a type, the object booleanWitness has the type ⟨ T : Type ⟩ {\displaystyle \langle {\textsf {T}}:{\text{Type}}\rangle } . Additionally, the object booleanWitness has the member value that is assigned the value true of type Boolean. Since the value of booleanWitness.T is Boolean, the object booleanWitness has the type ⟨ value : booleanWitness.T ⟩ {\displaystyle \langle {\textsf {value}}:{\textsf {booleanWitness.T}}\rangle } . Overall, the object booleanWitness has the intersection type ⟨ T : Type ⟩ ∩ ⟨ value : booleanWitness.T ⟩ {\displaystyle \langle {\textsf {T}}:{\text{Type}}\rangle \cap \langle {\textsf {value}}:{\textsf {booleanWitness.T}}\rangle } . Therefore, presenting self-reference as dependency, the object booleanWitness has the dependent intersection type ( x : ⟨ T : Type ⟩ ) ∩ ⟨ value : x . T ⟩ {\displaystyle (x:\langle {\textsf {T}}:{\text{Type}}\rangle )\cap \langle {\textsf {value}}:x.{\textsf {T}}\rangle } .

Alternatively, the above minimalistic example can be described using *dependent record types*.[16] In comparison to dependent intersection types, dependent record types constitute a strictly more specialized type theoretic concept.[12]

## Intersection of a type family

An **intersection of a type family**, denoted ⋂ x : σ τ {\textstyle \bigcap _{x:\sigma }\tau } , is a [dependent type](/source/Dependent_type) in which the type τ {\displaystyle \tau } may depend on the term variable x {\displaystyle x} . In particular, if a term M {\displaystyle M} has the type ⋂ x : σ τ {\textstyle \bigcap _{x:\sigma }\tau } , then for *each* term N {\displaystyle N} of type σ {\displaystyle \sigma } , the term M {\displaystyle M} has the type τ [ x := N ] {\displaystyle \tau [x:=N]} . This notion is also called *implicit [Pi type](/source/Dependent_type#Pi_type)*,[17] observing that the argument N {\displaystyle N} is not kept at term level.

## Comparison of languages with intersection types

Language Actively developed Paradigm(s) Status Features C# Yes[18] Functional Imperative Object-oriented Under discussion[19] Additionally, generic type parameters can have constraints that require their (monomorphized) type-arguments to implement multiple interfaces, whereupon the runtime type represented by the generic type parameter becomes an intersection-type of all listed interfaces. Ceylon No[20] Object-oriented Supported[21] Type refinement Interface composition Subtyping in width F# Yes[22] Functional Imperative Object-oriented Under discussion[23] ? Flow Yes[24] Functional Imperative Object-oriented Scripting Supported[25] Type refinement Interface composition Forsythe No Imperative Supported[26] Function type intersection Distributive, co- and contravariant function type subtyping Java Yes[27] Imperative Object-oriented Supported[28] Type refinement Interface composition Subtyping in width PHP Yes[29] Functional Imperative Object-oriented Scripting Supported[30] Type refinement Interface composition Scala Yes[31] Functional Imperative Object-oriented Supported[32][33] Type refinement Trait composition Subtyping in width TypeScript Yes[34] Functional Imperative Object-oriented Scripting Supported[6] Arbitrary type intersection Interface composition Subtyping in width and depth Whiley Yes[35] Functional Imperative Supported[36] ?

## References

1. **[^](#cite_ref-BCD83_1-0)** Barendregt, Henk; Coppo, Mario; [Dezani-Ciancaglini, Mariangiola](/source/Mariangiola_Dezani-Ciancaglini) (1983). "A filter lambda model and the completeness of type assignment". *Journal of Symbolic Logic*. **48** (4): 931–940. [doi](/source/Doi_(identifier)):[10.2307/2273659](https://doi.org/10.2307%2F2273659). [JSTOR](/source/JSTOR_(identifier)) [2273659](https://www.jstor.org/stable/2273659). [S2CID](/source/S2CID_(identifier)) [45660117](https://api.semanticscholar.org/CorpusID:45660117).

1. **[^](#cite_ref-2)** Palsberg, Jens (2012). "Overloading is NP-Complete". *Logic and Program Semantics*. Lecture Notes in Computer Science. Vol. 7230. pp. 204–218. [doi](/source/Doi_(identifier)):[10.1007/978-3-642-29485-3_13](https://doi.org/10.1007%2F978-3-642-29485-3_13). [ISBN](/source/ISBN_(identifier)) [978-3-642-29484-6](https://en.wikipedia.org/wiki/Special:BookSources/978-3-642-29484-6).

1. **[^](#cite_ref-3)** Henk Barendregt; Wil Dekkers; Richard Statman (20 June 2013). [*Lambda Calculus with Types*](https://books.google.com/books?id=2UVasvrhXl8C&pg=PR1). Cambridge University Press. pp. 1–. [ISBN](/source/ISBN_(identifier)) [978-0-521-76614-2](https://en.wikipedia.org/wiki/Special:BookSources/978-0-521-76614-2).

1. **[^](#cite_ref-G96_4-0)** Ghilezan, Silvia (1996). ["Strong normalization and typability with intersection types"](https://doi.org/10.1305%2Fndjfl%2F1040067315). *Notre Dame Journal of Formal Logic*. **37** (1): 44–52. [doi](/source/Doi_(identifier)):[10.1305/ndjfl/1040067315](https://doi.org/10.1305%2Fndjfl%2F1040067315).

1. **[^](#cite_ref-5)** Kfoury, A.J.; Wells, J.B. (January 2004). "Principality and type inference for intersection types using expansion variables". *Theoretical Computer Science*. **311** (1–3): 1–70. [doi](/source/Doi_(identifier)):[10.1016/j.tcs.2003.10.032](https://doi.org/10.1016%2Fj.tcs.2003.10.032).

1. ^ [***a***](#cite_ref-TS_6-0) [***b***](#cite_ref-TS_6-1) ["Intersection Types in TypeScript"](https://www.typescriptlang.org/docs/handbook/advanced-types.html#intersection-types). Retrieved 2019-08-01.

1. **[^](#cite_ref-7)** Giuseppe Castagna, Programming with Union, Intersection, and Negation Types, [https://arxiv.org/pdf/2111.03354](https://arxiv.org/pdf/2111.03354) p. 7 Also chapter 12 in "The French School of Programming", Springer 2024, ISBN 978-3-031-34517-3

1. **[^](#cite_ref-Wells_8-0)** Wells, J.B. (2003). "The Essence of Principal Typings". *ICALP '02: Proceedings of the 29th International Colloquium on Automata, Languages and Programming*. pp. 913–925.

1. **[^](#cite_ref-9)** Damiani, Ferruccio. "Rank 2 intersection types for modules". *PPDP '03: Proceedings of the 5th ACM SIGPLAN international conference on Principles and practice of declarative programming*.

1. **[^](#cite_ref-10)** Castagna, Giuseppe; Lanvin, Victor. "Gradual Typing with Union and Intersection Types". *ICFP 2017*.

1. **[^](#cite_ref-11)** Giuseppe Castagna, Mickaël Laurent, Kim Nguyễn, Polymorphic Type Inference for Dynamic Languages, Proceedings of the ACM on Programming Languages (POPL) 2024, p. 40:6

1. ^ [***a***](#cite_ref-K03_12-0) [***b***](#cite_ref-K03_12-1) Kopylov, Alexei (2003). "Dependent intersection: A new way of defining records in type theory". *18th IEEE Symposium on Logic in Computer Science*. LICS 2003. IEEE Computer Society. pp. 86–95. [CiteSeerX](/source/CiteSeerX_(identifier)) [10.1.1.89.4223](https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.89.4223). [doi](/source/Doi_(identifier)):[10.1109/LICS.2003.1210048](https://doi.org/10.1109%2FLICS.2003.1210048).

1. **[^](#cite_ref-13)** ["Type declarations in Scala"](https://www.scala-lang.org/files/archive/spec/2.12/04-basic-declarations-and-definitions.html#type-declarations-and-type-aliases). Retrieved 2019-08-15.

1. **[^](#cite_ref-14)** Amin, Nada; Grütter, Samuel; Odersky, Martin; Rompf, Tiark; Stucki, Sandro (2016). "The Essence of Dependent Object Types". [*A List of Successes That Can Change the World*](https://infoscience.epfl.ch/record/215280/files/paper_1.pdf) (PDF). Lecture Notes in Computer Science. Vol. 9600. Springer. pp. 249–272. [doi](/source/Doi_(identifier)):[10.1007/978-3-319-30936-1_14](https://doi.org/10.1007%2F978-3-319-30936-1_14). [ISBN](/source/ISBN_(identifier)) [978-3-319-30935-4](https://en.wikipedia.org/wiki/Special:BookSources/978-3-319-30935-4).

1. **[^](#cite_ref-15)** ["Singletons in the Scala shapeless library"](https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/singletons.scala). *[GitHub](/source/GitHub)*. Retrieved 2019-08-15.

1. **[^](#cite_ref-16)** Pollack, Robert (2000). "Dependently typed records for representing mathematical structure". *Theorem Proving in Higher Order Logics, 13th International Conference*. TPHOLs 2000. Springer. pp. 462–479. [doi](/source/Doi_(identifier)):[10.1007/3-540-44659-1_29](https://doi.org/10.1007%2F3-540-44659-1_29).

1. **[^](#cite_ref-17)** Stump, Aaron (2018). ["From realizability to induction via dependent intersection"](https://doi.org/10.1016%2Fj.apal.2018.03.002). *Annals of Pure and Applied Logic*. **169** (7): 637–655. [doi](/source/Doi_(identifier)):[10.1016/j.apal.2018.03.002](https://doi.org/10.1016%2Fj.apal.2018.03.002).

1. **[^](#cite_ref-18)** ["C# Guide"](https://csharp.net/). Retrieved 2019-08-08.

1. **[^](#cite_ref-19)** ["Discussion: Union and Intersection types in C Sharp"](https://github.com/dotnet/csharplang/issues/399). *[GitHub](/source/GitHub)*. Retrieved 2019-08-08.

1. **[^](#cite_ref-20)** ["Eclipse Ceylon™"](https://projects.eclipse.org/projects/technology.ceylon/). 19 July 2017. Retrieved 2023-08-16.

1. **[^](#cite_ref-Cey_21-0)** ["Intersection Types in Ceylon"](https://ceylon-lang.org/documentation/tour/types/#intersection_types). 19 July 2017. Retrieved 2019-08-08.

1. **[^](#cite_ref-22)** ["F# Software Foundation"](https://fsharp.org/). Retrieved 2019-08-08.

1. **[^](#cite_ref-23)** ["Add Intersection Types to F Sharp"](https://github.com/fsharp/fslang-suggestions/issues/600). *[GitHub](/source/GitHub)*. Retrieved 2019-08-08.

1. **[^](#cite_ref-24)** ["Flow: A Static Type Checker for JavaScript"](https://web.archive.org/web/20220408204727/https://flow.org/en/). Archived from [the original](https://flow.org/en/) on 2022-04-08. Retrieved 2019-08-08.

1. **[^](#cite_ref-25)** ["Intersection Type Syntax in Flow"](https://flow.org/en/docs/types/intersections/#intersection-type-syntax). Retrieved 2019-08-08.

1. **[^](#cite_ref-26)** Reynolds, J. C. (1988). Preliminary design of the programming language Forsythe.

1. **[^](#cite_ref-27)** ["Java Software"](https://www.oracle.com/java/). Retrieved 2019-08-08.

1. **[^](#cite_ref-28)** ["IntersectionType (Java SE 12 & JDK 12)"](https://docs.oracle.com/en/java/javase/12/docs/api/java.compiler/javax/lang/model/type/IntersectionType.html). Retrieved 2019-08-01.

1. **[^](#cite_ref-29)** ["php.net"](https://php.net).

1. **[^](#cite_ref-30)** ["PHP.Watch - PHP 8.1: Intersection Types"](https://php.watch/versions/8.1/intersection-types).

1. **[^](#cite_ref-31)** ["The Scala Programming Language"](https://scala-lang.org/). Retrieved 2019-08-08.

1. **[^](#cite_ref-32)** ["Compound Types in Scala"](https://www.scala-lang.org/files/archive/spec/2.12/03-types.html#compound-types). Retrieved 2019-08-01.

1. **[^](#cite_ref-33)** ["Intersection Types in Dotty"](https://dotty.epfl.ch/docs/reference/new-types/intersection-types.html). Retrieved 2019-08-01.

1. **[^](#cite_ref-34)** ["TypeScript - JavaScript that scales"](https://www.typescriptlang.org/). Retrieved 2019-08-01.

1. **[^](#cite_ref-35)** ["Whiley: an Open Source Programming Language with Extended Static Checking"](http://whiley.org/). Retrieved 2019-08-01.

1. **[^](#cite_ref-36)** ["Whiley language specification"](https://web.archive.org/web/20200116120135/http://whiley.org/download/WhileyLanguageSpec.pdf) (PDF). Archived from [the original](http://whiley.org/download/WhileyLanguageSpec.pdf) (PDF) on 2020-01-16. Retrieved 2019-08-01.

v t e Data types Uninterpreted Bit Byte Trit Tryte Word Bit array Numeric Arbitrary-precision or bignum Complex Decimal Fixed point Block floating point Floating point Reduced precision Minifloat Half precision bfloat16 Single precision Double precision Quadruple precision Octuple precision Extended precision Long double Integer signedness Interval Rational Reference Address physical virtual Pointer Text Character String null-terminated Composite Algebraic data type generalized Array Associative array Class Dependent Equality Inductive Intersection List Object metaobject Option type Product Record or Struct Refinement Set Union tagged Other Any type Boolean Bottom type Collection Enumerated type Exception Function type Opaque data type Recursive data type Semaphore Stream Strongly typed identifier Type class Empty type Unit type Void Related topics Value Abstract data type Boxing Data structure Generic Kind metaclass Parametric polymorphism Primitive data type Interface Subtyping Type constructor Type conversion Type system Type theory Variable

---
Adapted from the Wikipedia article [Intersection type](https://en.wikipedia.org/wiki/Intersection_type) by Wikipedia contributors ([contributor history](https://en.wikipedia.org/wiki/Intersection_type?action=history)). Available under [Creative Commons Attribution-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-sa/4.0/). Changes may have been made.
