Help with Typed Luau and Dictionaries

When a dictionary’s key type is specified, its recommendations become cluttered (see below). Does anyone know why? I’m still improving my familiarity with types, so any help is appreciated.

Intended behavior where recommendations appear correctly:

Code_Q5WpJYDT4D

But when specifying the types, the recommendations now appear cluttered when typing Args.:

Code_kReRzjQac4

export type Argument = {
	description: string,
	parse: () -> (),
}

local Args:{[string]: Argument} = {
    ["player"] = {
        description = "",
        parse = function() end,
    },

    ["color"] = {
        description = "",
        parse = function() end,
    },

    ["speed"] = {
        description = "",
        parse = function() end,
    },
}

return Args

This is most likely due to whatever extension you’re using paired with VS Code, this doesn’t happen in the Roblox IDE

Wait scrap that, I didn’t realise you were setting the keys to a string. Basically you’re telling Roblox that dictionary can have any string at all as a key and to ignore whatever type Roblox auto-assigns it, if you need to set specific string values as keys do

local Args: {['player'|'color'|'speed']: Argument}
1 Like

In studio it also appears to stop:

RobloxStudioBeta_7GCERphSXC

1 Like

Yes sorry didn’t realise you were setting the key’ type to string, I edited my reply

Thanks for the help! This is a great suggestion… and I assumed this would work too, but bizarrely it still doesn’t appear to be recommended still in both studio and VSC:

RobloxStudioBeta_yMNezOq1Qg

1 Like

You’ve accidentally added parentheses inside the brackets!

1 Like

I have just tested what I made and it seems like Roblox doesn’t like what I did there.

This is the fixed version, sorry for the confusion

type possibleKeys = 'niceKey'|'coolKey'
local args: {[possibleKeys]: string}
2 Likes

Removing the parentheses appears to throw an error, so I also tried making it into a Type, but this too doesn’t seem to work:

--!strict

export type Argument = {
	description: string,
	parse: () -> (),
}

type ArgumentType = "player" | "color" | "speed"

local Args:{[ArgumentType]: Argument} = {
	["player"] = {
		description = "",
		parse = function() end,
	},

	["color"] = {
		description = "",
		parse = function() end,
	},

	["speed"] = {
		description = "",
		parse = function() end,
	},
}

print(Args)

return Args

RobloxStudioBeta_dTyBtz1Gh1

1 Like

That’s odd. Seems like Luau doesn’t support that, even tho it shows the correct type

2 Likes

It’s funny because you’d assume this would work too… but sadly it doesn’t seem to :melting_face:

3 Likes

I tested it with the new Beta type solver as well, seems like it also doesn’t support that either. Hopefully this will be fixed with the full release of the new type solver

1 Like

Would you be okay if I reported this as a bug to roblox?

2 Likes

This seems like more of a bug then a solvable question. (Unless I understood your issue in the wrong way that is.)

Though it’s just a rough guess but try using the --!strict type-checking mode.

1 Like

Seems like that doesn’t work either, im pretty sure this unintended and indeed a bug

2 Likes

Yes because I really don’t have a idea on how this could be actually intended.

2 Likes

I agree, I’m going to test a few things and then write a bug report in a minute

1 Like

This isn’t really a solution but rather an explanation. From what I can tell, primitive dictionary types (denoted as {[k]: v}) only accept primitive values as keys in contrast to complex “dictionary” types (they behave more like objects), which allow you to use literal types as keys and assign each key a unique type. Now I don’t think this is a bug, especially when you consider that you’re denoting a common key and value type respectively anyways, which would defeat the purpose of using it in the first place.

2 Likes

Yes please, a bug report would be awesome if we can’t find any other reason why this would happen :pray:

If you share a link of that bug report afterwards I can make it the solution

2 Likes

The reason for denoting the string and Argument types is so that every sub-dictionary (such as Args.player) automatically registers as the type ‘Argument’. Unless there’s an alternative way to do this easily, enabling us to not specify types, I’d still consider this an unintended feature which would benefit from being reported.

2 Likes

Well the only way to achieve what you want is to just assign the argument type to each possible key literal, which could look something like:

type someType = {
  player: Argument,
  -- Alternatively ["player"]: Argument
  color: Argument,
  speed: Argument
}
1 Like