It does that because Record<string, ISprite> can have any string as a key. The UI can't hint every string.
You can give the UI further information to make it show monster and player for auto-completion by using an intersection between a type with those named properties and Record<string, ISprite> (but keep reading, you may not need to):
export let sprites: {monster: ISprite, player: ISprite} & Record<string, ISprite> = {
// −−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
monster: {
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
},
player: {
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
}
};
Playground link
However:
I believe I require this annotation, because one of my functions only takes ISprite types.
That's fine. Without any type annotation at all, the values your object has on its monster and player properties are compatible with ISprite, so you can pass them to a function expecting ISprite. TypeScript's type system is structural (based on shapes of objects), not nominal (based on names of types), so it's happy to accept any object as an ISprite as long as it has all the necessary properties with compatible types. This works just fine, for instance:
export let sprites = {
monster: {
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
},
player: {
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
}
};
function example(sprite: ISprite) {
console.log(sprite);
}
example(sprites.monster); // <=== Perfectly happy
Playground link
If you want the type name, or hinting for the members of ISprite as you're writing futher entries in sprites, you could give yourself a function:
makeSprite(sprite: ISprite) {
return sprite;
}
It looks like a do-nothing, and it is — at runtime. (Don't worry, it's not expensive). But at authoring time, it lets you do this:
export let sprites = {
monster: makeSprite({
textureName: "monster",
frame: new Frame(0, 0, 32, 41),
origin: new Vec2(16, 28),
zIndex: -1
}),
player: makeSprite({
textureName: "player",
frame: new Frame(0, 0, 32, 32),
origin: new Vec2(15, 32)
})
};
As you're adding entries, you'll be prompted with the property names from ISprite while you're writing the sprite argument for makeSprite.