Reputation: 10228
TypeScript allows implicitly casting from any
to a stronger type. Considering deserialized JSON is of type any
, this behavior allows many type errors and breaks typings.
What compiler or linting options can I use to block implicitly casting from any
to a stronger type?
Repro This operation should be flagged for allowing casting from any
to a stronger type.
const o = JSON.parse("");
const s: string = o.twinlakes;
Upvotes: 6
Views: 1884
Reputation: 4215
In additiona to Josh's answer, since the type check takes place during runtime, you can try using the 'as
' keyword to cast the value from 'any
' to the type you want.
const o = JSON.parse("{\"twinlakes\":\"Value\"}");
const s: string = (o as any).twinlakes;
How that works
Upvotes: 0
Reputation: 3420
If you haven't yet, try enabling the TypeScript --noImplicitAny
compiler flag to stop declarations from accidentally forgetting to mark types of things that can't be inferred. This'll stop code such as function takesData(data) { /* ... */ }
from allowing their data
variables to "implicitly" be type any
.
Edit January 2023: the correct answer is now to use typescript-eslint:
Additionally, there are several ESLint rules from typescript-eslint you can use for any
s that can sneak in even with --noImplicitAny
:
@typescript-eslint/no-unsafe-argument
: Disallows calling a function with a value with type any.@typescript-eslint/no-unsafe-assignment
: Disallows assigning a value with type any
to variables and properties.@typescript-eslint/no-unsafe-call
: Disallows calling a value with type any
.@typescript-eslint/no-unsafe-member-access
: Disallows member access on a value with type any
.@typescript-eslint/no-unsafe-return
: Disallow returning a value with type any
from a function.You can enable those rules individually in your ESLint config to use them in your project. Alternately, they're all enabled if you extend from the plugin:@typescript-eslint/strict
configuration.
Finally, as Titian mentions in the comments, consider using unknown
in your code in any place you'd have wanted to use any
. unknown
is similar to any
but TypeScript will enforce that you properly type narrow unknown
values before using them unsafely.
The answer below is outdated because TSLint is deprecated. Please see above for the answer with typescript-eslint.
Additionally, there are a couple TSLint rules that help here:
no-any
: Disallows usages of any
as a type declaration. Use this to stop declarations from including any
in them, e.g. let data: any = {/*...*/}
.no-unsafe-any
: Disallows accidentally using any
in an unsafe way. This is different from no-any
in that you might still be using any
types without knowing it: for example, let data = JSON.parse("{}");
.Upvotes: 9