Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can an argument ever be of the wrong type in TypeScript?

Tags:

typescript

In JavaScript:

function doSomething(mybar) {
  if (!(mybar instanceof Bar)) throw new TypeError("mybar");
  // ...other guard clauses
}

In TypeScript:

function doSomething(mybar: Bar) {
  // is guard clause ALWAYS redundant?
  // ...other guard clauses
}

I like to validate inputs with guard clauses. So in JavaScript I'd test that mybar is an instance of Bar, and if it isn't then I'd throw a TypeError.

In TypeScript is mybar guaranteed to be the correct type? (And thus eliminate the need for that first guard clause)


UPDATE

There are a few good answers below, which range from "it's definitely possible" to "it could happen" to "it can't happen".

So maybe a good way to phrase the question is - if it's possible that the wrong type is supplied at runtime, what is the mechanism by which that would happen? A bug in typecasting for example?

like image 353
lonix Avatar asked Jan 02 '23 09:01

lonix


1 Answers

instanceof is a test if the object is an instance of Bar. While this means the type of the parameter is also Bar the reverse is not necessarily true. Typescript uses structural typing, so any object with the structure of Bar will be compatible with the function parameter. So this this code is perfectly valid:

class Bar {
    bar: number;
}
function doSomething(p: Bar) { }
doSomething({
    bar: 10
})

When you have private properties, you can't 'fake' the object so easily, but even then, we can always assert to any:

class Bar {
    private bar: number;
}
function doSomething(p: Bar) { }
doSomething({ // error now
    bar: 10
})
doSomething({ // breaking out of type safety
    bar: 10
} as any)

And if your code-base is not entirely TS, then any type safety goes out the window, JS can call your TS function with whatever it pleases.

Does this mean you should always include the check ? I would argue against it. JS is pretty loose with its types (and so is TS), and this is what your users expect. If it quacks like a duck it is a duck, the old JS mantra goes. If the object has the properties to work with your function it should work with your function regardless of how it was created.

like image 84
Titian Cernicova-Dragomir Avatar answered Feb 16 '23 21:02

Titian Cernicova-Dragomir