Even though the notion of intrinsic types might baffle the reader, I will not define them right away, as I want to introduce the concept using a practical example. I would love to start the article with the following question, something I have asked myself in various forms over the years:

In an ideal, statically-typed language, how could one define the string capitalisation type, using the properties of its type system?

I could substitute string capitalisation with string permutation and the issue still remains valid, as long as it touches not the abstraction of types, but their intrinsic properties.

Solving the Assignment

The way I wrote the aforementioned assignment grants a lot of freedom in regards to choosing the utilised type system. However, one must recognise implicit requirements for certain features, like generics, string literals or inheritance. Since ordered lists of characters make strings, the question “which encoding applies to characters?” requires an instant answer.

I would name the type CapitalizedString and define it as a parametrised type (or a generic type, depends on the domain language of the chosen type system) with the single parameter T constrained to a string literal type. All characters in strings should adhere to the UTF-8 encoding. One could write it down easily using pseudocode in the following fashion:

type CapitalizedString<T extends string literal> = ...

By definition, if the string literal in question has no characters, the operation has obviously no effect on it. Otherwise, capitalisation alters only the first character of the string in question, leaving the rest unchanged. To uppercase a character, the type system needs to support it ad hoc, as defining it explicitly in the type system sounds impractical for UTF-8 characters due to complexity of such an algorithm (I find it inadvisable even for ASCII characters).

Therefore, the compiler itself must provide implementation of uppercasing any UTF-8 character, making the uppercase operation an ad hoc, or rather an intrinsic property of the type system. There exist multiple ways of declaring such a property in type definitions, for example:

intrinsic type Uppercase<T extends character>; 
type Uppercase<T extends character> = intrinsic;

An avid reader might note that the aforewritten definitions provide no return type explicitly — since the compiler performs the operation, nobody knows the return type beforehand. The type system might define uppercasing as an unary operator, accepting a single character, as shown in the following snippet:

type UppercaseA = uppercase 'a';

In the end, the CapitalisedString type boils down to the following definition:

type CapitalisedString<T extends string literal> =
    T === '' ? '' : Uppercase<T[0]> + T[1...];

In order for the definition to work, the type system in question requires:

  • an ability for equality comparison of two string literal types,
  • a possibility to access both the n-th character and a range of characters of any string literal type,
  • permission to use conditional statements in type definitions.

#javascript #typescript #type-systems

Intrinsic Types in TypeScript
2.30 GEEK