New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type #35859
Comments
This is a question, not a bug, please use SO for questions. (see this it will help) |
im sorry, thanks btw for the tips. im a newbie |
Bad - the reason for the error is the Better - the reason the error disappears is because now we are telling the compiler the Best - |
@alexandermckay What if I have this scenario: type props = {
type: string
}
const style = styles[props.type]
const styles = StyleSheet.create({
base: {
...spacing.medium,
padding: 10,
textAlign: "center",
textAlignVertical: "center",
fontWeight: "bold",
fontSize: 18,
height: 50,
},
primary: {
backgroundColor: colors.purple,
color: colors.white,
},
secondary: {
backgroundColor: "transparent",
color: colors.purple,
borderColor: colors.purple,
borderWidth: 2,
},
} It complains: |
Same question here, I have const LEVEL_DEBUG = 1;
const LEVEL_FINE = 2;
const LOG_LEVELS = {
info: LEVEL_INFO,
debug: LEVEL_DEBUG,
fine: LEVEL_FINE,
};
let logLevel: string = environment.logLevel;
if (!logLevel) {
logLevel = 'info';
}
let _level = LOG_LEVELS[logLevel.toLowerCase()]; // here it complains |
@greenlaw110 const LEVEL_DEBUG = 1;
const LEVEL_FINE = 2;
const LOG_LEVELS: {[key:string]: number} = {
debug: LEVEL_DEBUG,
fine: LEVEL_FINE,
};
let logLevel:string = 'debug';
if (!logLevel) {
logLevel = 'info';
}
const getKeyValue = <T extends object, U extends keyof T>(obj: T) => (key: U) =>
obj[key];
let _level = getKeyValue(LOG_LEVELS)(logLevel);
console.log(_level); // 1 |
Just found this blog post, which was very helpful, and wanted to paste some code here that I think is slightly more straight forward than the code included here so far. If you have the following object: const unitsOfTime = {
millisecond: 1,
second: 60,
hour: 60 * 60,
day: 24 * 60 * 60,
month: 30 * 24 * 60 * 60,
year: 365 * 24 * 60 * 60
}; You can declare types for the keys and values in that object like so: const unitsOfTime: { [unit: string]: number } = {
millisecond: 1,
second: 60,
hour: 60 * 60,
day: 24 * 60 * 60,
month: 30 * 24 * 60 * 60,
year: 365 * 24 * 60 * 60
}; |
Hey, if I do this my object will have the following shape when I hove over it: const unitsOfTime: {
[unit: string]: number;
} so auto-complete is no longer available, am I missing something? |
The workarounds provided here are not recommended for Object.keys. If you really want to iterate over known values on an object, you can't know that the object doesn't have additional properties at runtime. I've provided a TypeScript Playground example that demonstrates the runtime error that can occur. |
In addition to the answers, people could also try to use interfaces :)
|
Unfortunately, weakly typed solutions make autocompletion no longer work. |
I am a bit confused by this specific type checking.
Going further with the example above: const unitsOfTime = {
millisecond: 1,
second: 60,
hour: 60 * 60,
day: 24 * 60 * 60,
month: 30 * 24 * 60 * 60,
year: 365 * 24 * 60 * 60
};
unitsOfTime[someStringInput] // Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '...' I see 3 ways of bypassing this: // Adding a looser type:
const unitsOfTime: { [unit: string]: number } = {...}
// wrong because it makes it possible to also use a string in cases where I might not want to accept a string that is not specific.
// Augmenting the type of the indexing key:
const time = unitsOfTime[someStringInput as keyof typeof unitsOfTime]
// even worse because it communicates the idea that the key **IS** one of unitsOfTime even though it might not be.
// Typescript won't tell the difference but there is a case where things will break.
// Addind a looser type at indexing site:
const time = (unitsOfTime as Record<string, number>)[someStringInput]
// ok, but it shouldn't be necessary... ...What I would expect: This way I could do; const unitsOfTime = {...}
const time = unitsOfTime[someStringInput] // type of time is: number | undefined
if (!time) {
// handle missing unit
}
// type of time is: number
// continue with time |
For those of you having this issue with typescript: // error
Like @alexandermckay said, we need to specify that the current record's keys are of type "string"
So extend your interfaces with Record<string, any>, or generic types to get rid of any. Hope this helps. |
The idea would be @mnowotnik, that you use this interface for an object which can have changing key names, or dynamically set key names, during run-time.
If people are using this solution over a simple interface then it could be a faulty implementation or just bad code practice. This solution is not to be used to help in writing code faster, but so that people do not use |
@pke I have the same case? could you solve it? |
The following snippet also causes this error to be emitted: let some_mapping = {"key1": "value1", "key2": "value2", "key3": "value3"};
let v = "key1";
if (v in some_mapping) {
let a = some_mapping[v];
console.log("a is ${a}");
} Shouldn't the inferred type of v inside the if branch become: |
TypeScript Version: 3.0.1
Code
The text was updated successfully, but these errors were encountered: