Type checking dictionaries

I have this code snippet with type checking:

type Settings = {
	["Audio"]: {
		MainVolume: number
	},
}

function doThing(settingTable: Settings)
	for category: string, list: any in settingTable do
		
	end
end

Why does this warning pop up?
image

the category in the type is defined in double quotes, so why can it not be converted into a string here? Changing : string to : any or : unknown works.

2 Likes

I’d preferably use the iterator pairs() in this case.

When using the generalized iteration:
for k, v in T do

As the warning states, the index becomes an unknown type and therefore cannot be converted to a string.

If you wish to convert an unknown type to another type, you can read the Type refinements section of the Luau docs.

1 Like

You can’t iterate over string literal keys. You must provide a datatype indexer to iterate through a table:

type Settings = {
	[string]: { --> string indexer
		MainVolume: number
	},
}
2 Likes
local Settings = {
	Audio = {
		MainVolume = 0
	}
}

function doThing(settingTable)
	for category, list in pairs(settingTable) do
		-- Your logic here
	end
end
1 Like

That doesn’t solve OP’s issue? Their problem is with the type analysis, not with the actual code

2 Likes

image
I’m not getting an error in the text editor.

1 Like

O no I was trying to get the syntax error or whatever it was because it his picture is says a type unknown. The logic there was just for the for do

1 Like

Try enabling strict typing in your code.

2 Likes

ok yeah i got the error, but just by using pairs on the table fixes this.
for category: string, list: {any} in pairs(settingTable) do

1 Like

image

Apparently, having another type for just the audio key does fix the type checking issue even with --!strict on, but I’d rather not recommend it unless that’s the only feasible solution.

type audio = "Audio"

type Settings = {
	[audio]: {
		MainVolume: number
	}
}

function doThing(settingTable: Settings)
	for category: string, list: any in settingTable do
		
	end
end
1 Like

Unfortunately this wont be feasible for my use case since there would be multiple categories.

Why are you iterating through settings like that anyway? If you define table keys with literal values, that implies that you are not going to iterate through the table. This is intended and expected behavior.

I just have the settings sorted into categories in the actual data table.
The type is structured the same way.
I only have to loop through the settings like once in the entire game though.
This is how I thought it works, and it does work for autocomplete, but it causes a warning for this.

So is there any way to fix it, or do I just use pairs instead of generalized iteration?

EDIT: Seems like typecasting this also works:

function doThing(settingTable: Settings)
	for category: string, list: any in settingTable :: {[string]: any} do
		
	end
end

The point of type checking is to notify the intellisense that something is some value at a certain point. If you define table literals as keys with the keys having different layouts from each other, intellisense has no idea what the key and what value it will be at a certain time (hence “unknown”). This is why you need a general indexer for any of this to work.

If you want to iterate through a dictionary with a dictionary, your type would be:

type dictDict = {
    [string]: {
        [string]: any,
    }
}
1 Like