Javascsript is weird, and TypeScript, by design, does not even try to do anything to improve it at runtime. In Javascript, there are two kind of string values - primitive values and objects (or boxed strings).
So you have to check for both, or settle on using only one kind of string throughout the code. Usual recommendation is to avoid using String class at all. You can see the difference in javascript console:
let primitiveString = 'a';
>
typeof primitiveString === 'string'
> true // note that the result of runtime `typeof` is a string
primitiveString instanceof String
> false // primitiveString was not created with the String() constructor, of course
let objectString = new String('a');
>
typeof objectString === 'string'
> false // typeof objectString returns 'object'
primitiveString instanceof String
> true
objectString === primitiveString
> false
objectString == primitiveString
> true
I'd love something like
switch(typeof food) {
case string:
console.log(food)
case {value:string}:
console.log(food.value)
}
There are two different typeof operators in TypeScript.
One is compile-time only, it allows to refer to a type of some variable or function.
Another one is run-time typeof which is the same as in javascript, and it returns very limited amount of information because TypeScript does not generate any kind of type information available at runtime.
So, every time you want to check a type of the object at runtime, you need to write a series of if statements with different kind of checks, as appropriate for the situation:
typeof if you are checking for the kind of built-in type like string, number, booelan, function or object (object basically means "anything else")
instanceof if you want to know which constructor was used to create an object (note that if the value was created as object literal, it will be instance of Object, however it may well be compatible with some class because objects literals can have methods too)
in operator if you want to check if an object has some property or method
Array.isArray() to check if something is an array
and so on.
The compiler detects an error in your code
myValues.forEach(food => {
if (food instanceof String) {
console.log(food)
} else {
console.log(food.value) // <-- error here
}
})
because instanceof String will be false for primitive strings, so the false branch will be executed trying to access value property which does not exists on strings. The usual way to check for a string type is
if (typeof food === 'string') {
as explained in another answer.