#I'm having strange type declaration errors.

34 messages · Page 1 of 1 (latest)

alpine kraken
#

I'm currently developing a room system with Typescript and Redis.

But after developing for a time I came on this error, I think Typescript is confused somehow.

  No index signature with a parameter of type 'string' was found on type '{}'.ts(7053)
(alias) const gameModesEssentialSchemas: {
    [key: string]: object;
}
import gameModesEssentialSchemas```
#

types.ts

export interface GameType {
    name: string;
    mode: string;
    max_players: number;
    min_players: number;
}


export interface GameRoomData{
    game: string,
    max_players: number,
    min_players: number,
    mode: string,
    code: string,
    status: string,
    ready: boolean,
    creator: string,
    owner: string,
    connectedSockets: Array<string>,
}```
#

room_essentials/index.ts


const gameModesEssentialSchemas: {
    [key: string]: object;
} = {
    rps: {
        classic:
        {
            choices: {},
            scoreboard: {}
        }

    }
}

export default gameModesEssentialSchemas```
fathom summit
#

Can you make a demo on TS playground that shows the error?

#

I'm not sure where the error is in your code

alpine kraken
azure helmBOT
#
sueroo#0

Preview:ts interface GameType { name: string mode: string max_players: number min_players: number } interface GameRoomData { game: string max_players: number min_players: number mode: string code: string st ...

alpine kraken
#

Chatgpt helped me solving it:

I see. To achieve the structure you described with different games and different modes for each game, you can define a more complex set of interfaces and types. Here's how you can do it:

interface GameMode {
    [key: string]: {
        choices?: Record<string, any>;
        scoreboard?: Record<string, any>;
        [customProperty: string]: any;
    };
}

interface GameModesByGame {
    [game: string]: GameMode;
}

const gameModesEssentialSchemas: GameModesByGame = {
    rps: {
        classic: {
            choices: {},
            scoreboard: {}
        },
        differentMode: {
            choices: {},
            scoreboard: {},
            diffProp: {}
        }
    },
    ticTacToe: {
        classic: {
            randomprop: {}
        },
        differentMode: {
            diffprop: {}
        }
    }
};

// ... rest of your code

In this example, I've defined two interfaces: GameMode which represents a single game mode with optional properties, and GameModesByGame which represents a collection of game modes organized by game names.

You can then use these interfaces to annotate the gameModesEssentialSchemas object. The choices and scoreboard properties are common to all game modes, while any additional custom properties specific to a game mode can be added.

With this structure, TypeScript will be able to infer the types correctly when you access properties within the gameModesEssentialSchemas object based on the game and mode names.

#

.

it worked, idk if its recommended or what, just sharing here.

fathom summit
#

Cool

azure helmBOT
#
sandiford#0

Preview:ts ... meObject: GameType }) => { let a = gameObject["name"] // gameObject['name'] let b = gameObject["mode"] let c = gameModesEssentialSchemas[a] // gameModesEssentialSchemas[gameObject['name']] let d = c[b] // gameModesEssentialSchemas[gam ...

fathom summit
#

So I added these 4 lines to break down your code

#

You can see that c is type object

#

because gameModesEssentialSchemas is type { [key: string]: object; }

#

So you just need to change that type to

{
    [key: string]: {
        [key: string]: unknown
    }
}
#

or

#
Record<string, Record<string, unknown>>
#

You can replace unknown as needed, looks like for you it is something like

{
    choices: Record<string, ?your type here?>
    scoreboard: Record<string, ?your type here?>
}

I suggest giving this object its own named type, rather than making a super-deep nested type

#

So yeah chatGPT has given you essentially the same answer

interface GameMode {
    [key: string]: {
        choices?: Record<string, any>;
        scoreboard?: Record<string, any>;
        [customProperty: string]: any;
    };
}

interface GameModesByGame {
    [game: string]: GameMode;
}

If we combine these for visual clarity, it is

interface GameModesByGame {
    [game: string]: {
        [key: string]: {
            choices?: Record<string, any>;
            scoreboard?: Record<string, any>;
            [customProperty: string]: any;
        };
    };
}
#

However some warnings about this:

  1. I suggest not using interfaces. If you define the same interface twice, TS will combine them, making them a bit dangerous.
interface Foo {
    a: string
}

interface Foo {
    b: number
}

// Foo will be {
//    a: string
//    b: number
//}
#

So use type instead as it will error if redeclared

#

Also, don't use any. It's quite dangerous. If you don't know the type, use unknown. Otherwise specify a type. Use any only where the type never matters or where you just need to rush some code to a working state (emergencies) temporarily

#
[customProperty: string]: any;

The line about could also be a problem. A general string indexer will combine with the lines above. So choices must match the type of [customProperty: string]

azure helmBOT
#
sandiford#0

Preview:ts type T = { choices?: Record<string, number> scoreboard?: Record<string, boolean> [customProperty: string]: string }

fathom summit
#

In this example, where the types are different, errors are thrown

#

so you are likely to have future problems with that.

#

Generally you would just remover the index and specify any extra properties explicitly

#

if you need indexing, you can do something like this

type T = {
    choices?: Record<string, ?>
    scoreboard?: Record<string, ?>
    customProperties: {
        [key: string]: string
    }
}
#

To avoid conflicts

#

or make customProperties optional. I don't like optionals, because its annoying having to check them repeatedly

#

If you have different games, you probably want to use a union of exact shapes, with a discriminator to select between them

alpine kraken
#

@fathom summit okay man thanks for helping