I have a JS object myObject
, which is of type any
(I can't change the type, since it comes from a library).
If I try to access a property from myObject
I get no errors from typescript, since its type is any
. But myObject
could be undefined, and cause a crash.
Is it possible to get typescript to give an error in this case?
For example:
console.log(myObject.myProperty) // <-- if myObject is undefined, this will crash.
What I would like:
console.log(myObject.myProperty) // <-- typescript gives error
console.log(myObject?.myProperty) // <-- typescript gives no error
Is there a tsconfig for changing this behavior?
I am not looking for a solution using type unknown
.
No, TypeScript does not have support for a stricter interpretation of the any
type in which member access is disallowed unless it is known to be safe. Nor have I found any existing request for this particular feature. There was a proposal for a --strictAny
, which would have been different, but this was eventually closed in microsoft/TypeScript#24737 saying, among other things, that extra complexity around any
really didn't seem to be worth it, especially because there are many places in real world code where any
is intentionally used as a way to turn off type checking. So it is unlikely that TypeScript will add such functionality.
Instead, you could use a linter, like TypeScript ESLint. There is a no-unsafe-member-access
rule which "disallows member access on any variable that is typed as any
". This will cause the desired error to appear, but it will also cause undesired errors where you have done the proper type check. That is, it is more restrictive than you want:
declare const myObject: any;
myObject.myProperty // warning: unsafe access 😊
myObject?.myProperty // warning: unsafe access ☹
It doesn't look like there's any "perfect" way to proceed. I'd recommend that you copy the value to a variable of a non-any
type:
type MyAny = { [k: string]: any } | undefined | null;
const _myObject: MyAny = myObject
_myObject.myProperty; // error
_myObject?.myProperty; // okay
Or write a type checking function that narrows any
to more safely indexable type:
function nonNullish(x: any): x is { [k: string]: any } {
return x != null;
}
if (nonNullish(myObject)) {
myObject.myProperty // okay
}
Or maybe even push back on the typings provider for the library and say that any
is too loose of a type if the value might really be undefined
or null
at runtime. (If it can't, then the other option is to just stop worrying about it until and unless it does happen.)