Is Flexible Functions Possible?

Is it possible to use type annotations in Luau for a function that behaves differently based on receiving 2 or 4 parameters, and make it show up in the hovertext what amount parameters you need to input based on the amount of parameters?

image

My attempt:

3 Likes

Luau type analysis supports overloads:

-- Example
type a = (g: UDim2) -> any
type b = (t: any, d: any) -> number
type c = (e: string) -> string

local test: a & b & c

Result:

image

4 Likes

Wow awesome! Do you know if it is possible to add descriptions to each overload? Kinda like how engine functions adds descriptions

You can add descriptions via ScriptEditorService using plugins, but unfortunately, you cannot add them with the regular type analyzer just yet (however, I recall seeing a staff member say a while ago that they were considering this)

They should for sure add that to the regular type analyzer. You can make very nice modules if this was opened.

How would you use this in a function?

This is a pretty niche example, but an example nontheless.

-- Example
type overload_warn = (message: string, doWarn: boolean) -> ()
type overload_print = (message: string) -> ()

local console: overload_warn & overload_print do
    --[[ 
        this syntax isn't required for the function definition; 
        i just like to overcomplicate things sometimes.

        You can also define the function like this:
           local console: overload_warn & overloard_print = function
    --]]
    function console(message: string, doWarn: boolean?)
        if not doWarn then
            --! ! everything here works for 'overload_print'
            -- The 'doWarn' argument was not provided
            print(message) -- prints the message
            return
        end
        
        --! ! everything here works for 'overload_warn'
        warn(message) -- warns the message
    end
end

console("hello world!") -- prints "hello world!"
console("hello world!", true) -- warns "hello world!"

And when looking at the function’s type information, you will see the different options:

image

3 Likes

I do not know enough about luau annotations to simplify the logic. I am trying to make it so local AnyName: overload_print & overload_warn = console is not needed, it will be a pain to implement Overload functions in production like shown.

-- Example
type overload_print = (message: string) -> ()
type overload_warn = (message: string, doWarn: boolean) -> ()


local function console(message: string, doWarn: boolean?)
    if doWarn then
        warn(message) -- warns the message if doWarn is true
    else
        print(message) -- prints the message if doWarn is false or nil
    end
end

local AnyName: overload_print & overload_warn = console

AnyName("hello world!") -- prints "hello world!"
AnyName("hello world!",true) -- warns "hello world!"

If you’re asking about the type declaration, you can combine them into a single type like so:

type overload_print = (message: string) -> ()
type overload_warn = (message: string, doWarn: boolean) -> ()

-- Combines all the individual types into a single type that can be used
type method = overload_print & overload_warn

-- Use the single type on the function
local callback: method = function(...)

end

But if you’re asking if you can use the following function declaration with type analysis:

local function foo()

end

Unfortunately this wouldn’t work because the syntax doesn’t allow for manually assigning types to foo (hence the other two function declarations I used); you can only declare the return type of the function with this syntax


I may have misinterpreted your question, so please let me know if so

Let me rephrase my question. I want to make a big module with functions in it. In that module I don’t want to retype any function names like done on local console: overload_print & overload_warn = console. Instead I want it to be simple so you just define the function once and it does the overload checking in one go.

Sorry for the late response,

I understand a little better now; unfortunately the only way to do that is using this syntax:

local method: T = function(...)
   -- 'T' is the type that should be applied to the function (overloads)
end

method(2, 6, 8)

It doesn’t look as good as the local function foo(...) syntax, but it’s the only way to achieve what you want

My goal is to have a general way to set the function that works for both oop and normal scripting.

I thought of something like this, it is not valid code but you will get the idea:

	-- Example
	type overload_print = (message: string) -> ()
	type overload_warn = (message: string, doWarn: boolean) -> ()

	local function OverloadFunction(func, Annotation)
		Annotation = func
		func = Annotation
	end

	local function console(message: string, doWarn: boolean?)
		if doWarn then
			warn(message) -- warns the message if doWarn is true
		else
			print(message) -- prints the message if doWarn is false or nil
		end
	end

	local AnyName: overload_print & overload_warn
	
	OverloadFunction(console, AnyName)

	console("hello world!") -- prints "hello world!"
	console("hello world!",true) -- warns "hello world!"

The pain is the name for a general system, the way you provided is hardcoded.

Ohhhh, ok

Yea, I see what you want to do. Unfortunately, I don’t believe there’s a way to do that with the type analysis system (that I’m aware of). However, you can try to do something hacky to get around it (the system is flexible enough to be ‘directed,’ with some effort).

The system is largely manual (with a few automated exceptions).


This is the link to the type checking documentation:

You could try something with Generics (maybe?)

-- This is just an example of what generics looks like;
-- this doesn't actually do much for your issue
function foo<T>(x: T): T
    return x
end

Use the response here and put it in a module script.
Module:
wncolorBruisedDikdik

OtherScript:
gncolorUnhappyIbadanmalimbe

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