"Improving" the typing of Box is a little vague, but assuming you'd like Box to keep track of the type of value it contains, then I'd introduce a generic interface to represent the intended behavior:
interface Box<T> {
  inspect(): string;
  map<U>(f: (arg0: T) => U): Box<U>;
  fold<U>(f: (arg0: T) => U): U;
}
A Box<T>'s inspect method always produces a string.  Its map() method takes a callback turning a T into some other type U and produces a Box<U>, and fold takes a callback turning a T into some other type U and produces just a U.
Then you can annotate the function named Box as a generic one which accepts a value of type T and returns a Box<T>:
function Box<T>(x: T): Box<T> {
  return {
    inspect: () => `Box(${x})`,
    map: f => Box(f(x)),
    fold: f => f(x)
  }
}
Note how you can remove the annotations inside the implementation of Box because they are contextually typed by the expected Box<T> method parameter types.
Then when you use Box, you will see how the compiler keeps track of whether it is holding a number or a string (or anything else), and again the callbacks can be contextually typed so you can leave off their annotations:
const expr = Box(Math.PI / 2) // Box(1.5707963267948966)
  .map(x => Math.cos(x)) // Box(6.123233995736766e-17)
  .map(x => x.toFixed(4)) // Box("0.0000")
  .map(x => Number(x)) // Box(0)
console.log(expr.fold(x => x).toFixed(2)) // "0.00"
And the compiler will complain if you do the wrong thing, like treat a string as a number:
const badExpr = Box("Hello")
  .map(x => x.toFixed(2)); // error!
  // -------> ~~~~~~~
  // Property 'toFixed' does not exist on type 'string'.
Playground link to code