Reputation: 4116
I'm using this code with Svelte 3:
REPL: https://svelte.dev/repl/bf73fffc1b9442dfbcd492eaa9c048e1?version=3.35.0
<script lang="ts">
const players = {
men: {
john: "high",
bob: "low",
},
};
// const player = "bob"
$: player = "bob";
const test = players.men[player];
console.log(test); //prints undefined
</script>
{player} //bob
{test} //undefined
Typescript even tells me this:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ john: string; bob: string; }'.
No index signature with a parameter of type 'string' was found on type '{ john: string; bob: string; }'.ts(7053)
If I use const player = "bob"
it works!
Why?
Upvotes: 0
Views: 829
Reputation: 21926
You can't use a random string to access an object safely, which is why the compiler complains. The reason it doesn't complain when you use const
is that a constant string literal is known at compile time, and it can't change at runtime, so the compiler knows it's safe. There are a few ways around this, but the easiest (N.B. not safest) way is a cast:
const players = {
men: {
john: "high",
bob: "low",
},
};
// const player = "bob"
let player = "bob";
const test = players.men[player as keyof typeof players.men];
There may also exist a safer way to do this with the Svelte thing you are trying to use, typically when writing this sort of thing in TS I will use string literals or an enum to have the compiler ensure I'm not getting an unexpected undefined
:
enum Males {
JOHN = "john",
BOB = "bob"
}
const players: {
men: {
[key in Males]: string;
}
} = {
men: {
john: "high",
bob: "low",
},
};
const test2 = players.men[Males.JOHN];
Upvotes: 2