How to ensure optional properties become required at runtime in luau typechecking

I’m working with Luau’s type system and trying to refine types dynamically based on function arguments. I have a function that takes a table (props) with optional properties (e.g., Corner, Padding, Gradient, etc.). If a property like Corner is included in props, the return type should reflect that the resulting table now has a guaranteed UICorner.

But there isn’t an easy way to do this without ruining everything.

Things I have considered:

  • Overloads – The brute-force approach would be to manually write 2^N overloads for each possible combination of optional properties, horrible.
  • Recursive Typechecking – I tried using recursive type definitions similar to TypeScript’s mapped types, but Luau doesn’t seem to support them directly, also I don’t quite know how to use new luau type solver function properly in this case.

Example of What I Want:

local function create(props: { Corner: UICorner? }): { UICorner: UICorner }
    -- If `Corner` is provided, return type should guarantee `UICorner`
    return props
end

local _ = create({}) --key UICorner still exist

But ideally, I want this to work for multiple UI components without manually listing every combination.

TL;DR: Ensure the returned type includes a UI component when its key is provided.

Any help is appreciated!

If I am understanding what you are asking correctly, you can achieve this using generic types.

Generic Types allow you to vary the return type depending on the type of the arguments passed.

local function create<T>(props: T): T
    -- The return value is of the same type as the parameter passed
    -- So any key in props will be present in the type of the returned table
    return props
end

I hope this helps!

Edit:
If you only want to allow for certain entries in the returned type, consider using the union operator:

type UIComponents = {
    UICorner: UICorner,
}

local function create<T>(props: T): T|UIComponents
    return props
end

If you do this, only entries that are present in the UIComponents type and in the props table will be in the type of the returned value.

2 Likes

Hey, thanks for replying that is quite what I am asking for, but it is not perfect, there still issue of the typechecker mistaking that the key UICorner exist when it isn’t defined in the props’ argument.

1 Like

If you use the union operator like shown in the second example, this issue should not occur.

1 Like

Sorry for my mistake, I wasn’t checking on both platfrom, somehow luau lsp got this wrong(it was the new luau type solver option), ty so much!
image

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