== Why is this an issue?

In TypeScript, a type alias is a way to give a name to a specific type. It allows you to create a new name for an existing type, making your code more expressive and readable. This is especially useful when you are working with complex or lengthy types that you use frequently.

Type aliases should be preferred over complex types like unions or intersections for several reasons:

* Type aliases can make your code more readable and maintainable by giving meaningful names to complex types. When you use a type alias, it becomes clear what the type represents, making it easier for other developers (including your future self) to understand the code.
* Type aliases promote code reusability. When you define a type alias for a complex type, you can use that alias in multiple places throughout your codebase, reducing duplication and promoting consistency.
* Type aliases allow you to abstract away the underlying complexity of types. This promotes encapsulation by hiding implementation details behind a well-named alias, allowing you to change the underlying type in the future without affecting the code that uses the alias.
* If you need to modify a complex type, using a type alias means you only need to change the type definition in one place. This change will automatically apply to all usages of the alias.
* Type aliases communicate the intent of the type, making it easier for other developers to understand what the type represents. Complex unions and intersections, on the other hand, might require additional comments or documentation to explain their purpose.
* Using type aliases can help you avoid excessive nesting of complex types. Nested unions and intersections can quickly become hard to read and maintain, and type aliases can simplify the type definitions.

This rule enforces the rule of three for code refactoring and reports unions and intersections with three or more constituents appearing at least three times in the codebase.

[source,javascript,diff-id=1,diff-type=noncompliant]
----
function foo(x: string | null | number) { // Noncompliant: The union has three constituents and is duplicated three times in the code
  /* ... */
}

let bar: string | null | number = /* ... */;

function baz(): string | null | number {
  /* ... */
}
----

You should define a type alias for the union or intersection duplicated in the code and replace all their occurrences with the alias name.

[source,javascript,diff-id=1,diff-type=compliant]
----
type MyType = string | null | number;

function foo(x: MyType) {
  /* ... */
}

let bar: MyType = /* ... */;

function baz(): MyType {
  /* ... */
}
----

The rule disregards nullable types, irrespective of their frequency within the codebase. This includes types of the form `T | null | undefined`, where `T` can represent any type.

[source,javascript]
----
function foo(x: T | null | undefined) {
  /* ... */
}
----

== Resources
=== Documentation

* TypeScript Documentation - https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases[Type Aliases]
* TypeScript Documentation - https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html[Unions and Intersection Types]
* Wikipedia - https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming)[Rule of three (computer programming)]

ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Replace this [union|intersection] type with a type alias.


=== Highlighting

* Primary: first occurrence of the union/intersection
* Secondary: All other occurrences
** message: 'Following occurrence.'


'''
== Comments And Links
(visible only on this page)

=== on 14 Nov 2017, 22:02:10 Ann Campbell wrote:
\[~jeanchristophe.collet] there are no ``++//Noncompliant++`` comments. 



=== on 15 Nov 2017, 09:19:00 Jean-Christophe Collet wrote:
That's because it's not a particular line that is non compliant, but the repetition of the specific union.

=== on 27 Nov 2017, 19:04:40 Ann Campbell wrote:
\[~jeanchristophe.collet] I've updated the highlighting to match the 'Noncompliant' comment.

endif::env-github,rspecator-view[]
