Gradual typing could still keep some static guarantees if the static part were sound, e.g. you couldn't assign a dynamic-typed integer to a string-typed variable without checking the type at runtime first; which TypeScript isn't.
Elixir's new type system does much better here, as it determines whether a function actually guards for the right type at runtime ("strong arrows") and propagates the guarantees, or lack thereof, accordingly.
Elixir's new type system does much better here, as it determines whether a function actually guards for the right type at runtime ("strong arrows") and propagates the guarantees, or lack thereof, accordingly.