Ability to change function return type based on argument value

As a Roblox developer, it is currently impossible to change a function’s return type based on an argument value.

local function getProductInfo(infoType: Enum.InfoType): (ProductInfo | AssetInfo | GamePassInfo)
	-- return product info
end

This function currently returns either a ProductInfo, AssetInfo, or GamePassInfo, but the type checker doesn’t really know which one it actually is, even though it will always be directly determined by the InfoType passed to the function. Ideally it should be possible to define the relationship between argument values, especially EnumItems, and return types.

If Roblox is able to address this issue, it would improve my development experience because I would be able to have more precise type checking.

3 Likes

This already exists. It’s called generic typing.

local function State<T>(key: string, value: T): State<T>
	return {
		Key = key,
		Value = value
	}
end

local Activated = State("Activated", false)  -- State<boolean>
local TimesClicked = State("TimesClicked", 0)  -- State<number>

That’s not the OP’s issue here. They want to identify the enum type and use that to choose a different concrete return type - generics don’t do this.

1 Like

You are speaking about an input value rather an input type, right?

i’m pretty confused (mostly because of your example)

you could easily ignore the arguments passed and return something else

OP wants a mechanism like function overloading, Luau cant natively support this as a runtime feature due to how functions work, but I still believe it can work as a typechecking feature since the typechecker is declarative.

Here’s an example of function overloading in C# for example:

namespace OverloadedFunction {
  internal uint Add(uint a, uint b) {
    return a + b;
  }

  internal uint Add(uint a) {
    return a++; // idk if this is valid in cs
  }
}
3 Likes

Is there a reason these are not separate functions instead? Huge branches are usually pretty scary and are indicative of a function doing too much.

Regardless, if enum item constants were added (I’m not on that team, but it’s something that ought to exist), you’d be able to hack something together with type functions, with a signature that looks something like:

local function getProductInfo<I>(infoType: I): ProductInfoOf<I>

Or, even without enum item constants, you could use string constants here instead, which would work out of the box.

2 Likes

What I wrote is basically a wrapper for MarketplaceService:GetProductInfo(). I could technically split it into five identical functions with different signatures, but that turns out pretty bloated and also breaks the old “don’t repeat yourself” adage.

1 Like

Since the parameter’s type would be dependent on the value of its arguments, this would require Dependent-Typing. That is way out of scope, if not infeasible for the Luau typechecker.

Now this could be a different story if there was some type-universe distinction between different EnumItems, but otherwise there is no way to distinguish them apart.