Both TypeScript and Flow deduce the type \code{(number$\vee$string)$\to$number} for the function \code{foo} we defined in the introduction.\footnote{\label{null}Actually, they deduce as return type \code{number$\vee$null}, since both languages track the possibility that some operation may yield \code{null} results. Considering this would not pose any problem but clutter the presentation, so we omit such details.} Consider, next the following slight modification of that example

where \code{trim()} is the JavaScript library function that removes all blank spaces at the beginiing and end of a string. Now, the type deduced is \code{(number$\vee$string)$\to$(number$\vee$string)}, but it is clear that a better type for this function would be the following intersection type (Footnote~\ref{null} applies here, too):

As explained in the introduction, both TypeScript and Flow deduce the type

\code{(number$\vee$string)$\to$number} for the function \code{foo} we

defined.\footnote{\label{null}Actually, they

deduce as return type \code{number$\vee$null}, since both languages

track the possibility that some operation may yield \code{null}

results. Considering this would not pose any problem but clutter the

presentation, so we omit such details.}

As we have seen, a more precise type for this function is

@@ -20,7 +21,11 @@ type \code{number} or not (i.e., \code{(number$\vee$string)$\setminus$number}, t

should be enough for the system to deduce the type \eqref{tyinter}

even in the absence of an explicit type annotation.

In this section we show how to do it by using the theory of occurrence typing we developed in the first part of the paper. In particular we collect the different types the parameter of a function is assigned in its body to determine a partition of the domain types againt which check the body of the function. Let us consider an example more general than the one above.

In this section we show how to do it by using the theory of occurrence

typing we developed in the first part of the paper. In particular we

collect the different types the parameter of a function is assigned in

its body to determine a partition of the domain types againt which

to check the body of the function. Consider a more involved example

\begin{alltt}\color{darkblue}

function (x \textcolor{darkred}{: \(\tau\)}) \{

(x \(\in\) Real)

...

...

@@ -28,25 +33,28 @@ In this section we show how to do it by using the theory of occurrence typing we

: \{\(\neg\)x \}

\}

\end{alltt}

When $\tau$ is \code{Real|Bool} (we suppose that \code{Int} is a subtype of \code{Real}) we want to deduce for this function the

When $\tau$ is \code{Real|Bool} (we assume that \code{Int} is a

subtype of \code{Real}) we want to deduce for this function the

Here, for each arrow in the declared interface of the function, we

first typecheck the body of the function as usual (to check that the

arrow is valid) and collect the refined types for the parameter $x$.

Then we deduce all the possible output types for this refined input

types and add the resulting arrows to the type we deduce for the whole

function.

{\color{darkred} RANDOM THOUGHTS:

\kim{We define the rule on the type system not the algorithm. I think

we could do the same (by collecting type scheme) in $\psi$ but we

then need to choose a candidate in the type scheme \ldots}

A delicate point is the definition of the union

$\psi_1\cup\psi_2$. The simplest possible definition is the

component-wise union. This definition is enough to avoid the problem

...

...

@@ -210,16 +238,8 @@ of the ``if'' ... but it is probably better to check it by modifying

the rule of ``if'' (that is, add $\psi_\circ$ only for when it brings new

information).

}

It is not too difficult to generalize this rule when the lambda is typed by an intersection type. Indeed, even if the programmer has specified a particular intersection type for the function we may want to refine each of its arrow. This is exactly what the following rule does:

\beppe{Problem 1: is it true that this typing techniques captures all the ``inituitive cases''? That is to say, is it true that this typing and the semantics in which in type case we strip all ``negative'' casts off the resulting values are equivalent? That is they yield the to the same result (probably module the stripping of negatibe casts)?}