The indexer is so I can dynamically read from/assign to existing class members. E.g. test[something] = "Hi!";
My guess is you ran into this scenario when using noImplicitAny
:
class TestClass {
something: string = "";
}
const test: TestClass = new TestClass();
const key: string = "something";
test[key] // Error: Element implicitly has an 'any' type because type 'TestClass' has no index signature.
And so you added an index signature (as the error mentions) to make the error go away:
class TestClass {
something: string = "";
[index: string]: any;
}
However, as you've seen, this changes the type to allow any kind of access, not just known properties. This isn't what you want.
The real problem is that you are using an index lookup of type string
, so the compiler can't resolve it to a known property (since a string could be anything). If it was a known key, like "something"
, you'd get no error:
const test: TestClass = new TestClass();
const key = "something";
test[key] // OK
That works because key
is a literal type "something"
, not a general string
that could be anything. So most likely the real fix in your code is to constrain the key to known keys of the type. You can use keyof
and map types to help you.
function lookup(test: TestClass, key: keyof TestClass) {
return test[key]; // OK
}
lookup(test, "something"); // OK
lookup(test, "notInClass"); // Error
Alternative
Another option you have is to suppress implicit any index errors completely with a compiler option: suppressImplicitAnyIndexErrors
. This means that when dealing with a type that has no index signature you can still only use .
property access with known properties, so test.aPropertyNotInTheClass
is not allowed, but you can use index lookups with any key and you will get no compile error, you will just get the type any
. However keep in mind that since the index lookup is going to give you type any
it could be undefined
and you will get runtime errors if you don't check:
// with --suppressImplicitAnyIndexErrors
const test: TestClass = new TestClass();
const key = "aPropertyNotInTheClass";
test[key] // No compile error, but will be undefined
test[key].toUpperCase() // No compile error, but will be runtime error
This is the the type of error that noImplicitAny
exists to prevent. The suppressImplicitAnyIndexErrors
is loosening the restrictions since this is a known pain point but comes with pitfalls, which is why it is not enabled by default.