Why am I getting a typing error?

Hi! I have code spanning two modules:

    debounce = function(duration: number, is_per_player: boolean, rejection_callback)
        local global_debounce: boolean = false
        local local_debounce = {}
    
        return function(plr, model, action_id)
            if is_per_player and not local_debounce[plr] then
                local_debounce[plr] = true
                task.delay(duration, function()
                    local_debounce[plr] = nil
                end)
            
                return true
            elseif (not is_per_player) and not global_debounce then
                global_debounce = true
                task.delay(duration, function()
                    global_debounce = false
                end)

                return true
            end

            if rejection_callback then
                rejection_callback(plr, model, action_id)
            end

            return false
        end
    end
    action_service:observe_action(function(plr, model)
        if not model:GetAttribute("store_lights") then return end
        model:SetAttribute("on", not model:GetAttribute("on"))
    
    end, "toggle_store_light_lever", {
        action_service.filters.expect_model(false),
        action_service.filters.debounce(COOLDOWN, true, function(plr)
            notification_service:local_notification(plr, {
                title = "Error",
                description = "Lights are on cooldown",
            })
        end),
    })

The function on the first module is called by the second module

        action_service.filters.debounce(COOLDOWN, true, function(plr)
            notification_service:local_notification(plr, {
                title = "Error",
                description = "Lights are on cooldown",
            })
        end),

However, I’m getting a typing error:

TypeError: Type
‘<a, b>(any, a, b) → boolean’
could not be converted into
‘<a, b, c>(a, b, c) → boolean’; different number of generic type parametersLuau1000

TypeError: Type
‘<a, b>(any, a, b) → boolean’
could not be converted into
‘<a, b, c>(a, b, c) → boolean’
caused by:
Argument #2 type is not compatible.
Type ‘a’ could not be converted into 'a’Luau1000

If found out that if I move:

local local_debounce = {}

into the scope of the return function like so, the error goes away:

    return function(plr, model, action_id)
            local local_debounce = {}
            if is_per_player and not local_debounce[plr] then
                local_debounce[plr] = true
                task.delay(duration, function()
                    local_debounce[plr] = nil
                end)
            
                return true
            elseif (not is_per_player) and not global_debounce then
                global_debounce = true
                task.delay(duration, function()
                    global_debounce = false
                end)

                return true
            end

            if rejection_callback then
                rejection_callback(plr, model, action_id)
            end

            return false
        end

but obviously that breaks the logic of my code. I’m not sure if I’ve done anything wrong. How can I solve the error?

Without knowing where in the code the type errors are situated, my thoughts are that this code probably needs some annotations in your first module, where you define debounce, to allow Luau to figure out what’s happening here.

Luau cannot determine the type of plr in the callback returned from debounce, so it inserts a generic type in one case, and uses any in another. This is an oversight on our part, I think, but for now, you should try annotating either rejection_callback or the three arguments to the callback that debounce returns.

The reason moving local_debounce into the returned function is because that allows Luau to not care so much about what plr is - generics are tricky when they’re inferred in cases like this, and I think that’s what you’re running into.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.