I read from the TypeScript documentation, that you can't access properties from the type unknown:
// No property accesses, element accesses, or function calls
function f11(x: unknown) {
x.foo; // Error
x[5]; // Error
x(); // Error
new x(); // Error
}
But I don't understand why? If I can assign every value including an object, why can't I access the properties?
I'm batteling the following scenario: I have an object of type any
and I pass it to the Object.entries
method and then call forEach
.
Because it's of type any
, the forEach call argument will be an array with the first element being of type string and the second one of type unknown.
In my case, that second element is an object, but I can't access its properties without converting its type, which seems wrong to do.
Here is an example, which throws a TS error (just an abstraction, I know it doesn't make sense to declare it as any in this case):
const obj: any = {
val1: "someval",
val2: {
some: "some",
object: "object",
},
};
Object.entries(obj).forEach(el => {
if (el[1].some) {
console.log(el);
}
});
This could also just be wrong typings for the Object.entries
method I guess, but I'd still like to have explained, why I can't access properties of type unknown.
So as a summary my questions are:
Object.entries
return an array w/ element nr. 0 of type string and element nr. 1 of type any?I think that in order to address your question, it is important to give some context on any
vs unknown
. While you can find an exhaustive comparison list in the official TypeScript documentation, I think I can take some liberty and shorten the article to a few statements: any
is basically a one-type-fits-all and therefore is not type-safe. By type-safe I mean you can access a runtime property of any
that doesn't exist.
unknown
is different. unknown
is the opposite of any
in this regard. It represents a type-safe version of any
by stating "I won't pretend I fit everything because I don't". So unknown
requires additional casting to the desired type in order to work (because it doesn't possess any properties on its own).
Now, to the actual question. Why Object.entries
use unknown
instead of any
? Because it is safer to say "cast this unknown value to whatever you need before usage, I won't assume that I know anything about this type" than "I don't know what kind of type it is, but I'll assume that it has all possible properties of all possible types".