How do you make a function signature that takes in a type name as a string, and returns that type?

I have tried

type test = { 
        number: number,
        string: string,
        Instance: Instance
}

function something<R>(a: keyof<test>&R): index<test,R> [...] end

But this has issues because the &R ruins the typechecking for input but gives correct output.
I basically want this something function to work like Instance.new. How do I do this?

2 Likes

not sure what the provided code is… but check out typeof() which returns the type of the passed object as a string. ex. typeof("hi") would return "string"

1 Like

no, I want this special function to work like this:
hello(“Instance”) gives type annotations for Instance.
hello(“string”) gives string annotations

it’s kind of like Instance.new(“Part”) returns the Part type
and Instance.new(“TextButton”) returns the TextButton type

2 Likes

ohhh ic what you mean. why can’t you simply use strings? if you ever need to compare anything, you can just use typeof. anyways, i dont believe this is even possible

1 Like

I don’t think you understand my question.
Strings obviously work, but i’m asking if there is a way, with the current type system, to make a function signature that takes a string literal and returns the type with the name of the literal

1 Like

I believe I do.

As I said, I’m highly confident this is not possible. And if

What was the point in this topic?

The answers are all there. You just have to look for them.

Edit: What is your main goal - what are you trying to acheive with this function? I have a feeling this may be an XY problem

1 Like

Because it’s annoying to have to annotate every variable’s type if you want to have a function that can generate multiple types depending on the parameter, like Instance.new. With Instance.new(“Part”), you don’t have to do local p: Part = Instance.new("Part") just to get all of the script autocomplete magic. Point is, the function needs to guess the return type from a given string type name.

2 Likes

autocomplete probably

2 Likes

ok so after some research i found that lua doesnt support passing a list of types (like a type[] or an array of types) to create a union type automatically. unfortunately, you have to explicitly type in the union when defining function parameters or variables. this aligns with my previous statements.

edit: i think some languages actually do tho. sadly, not lua :frowning:

1 Like

No, you don’t. That’s the point of keyof! it creates a union for you of keys to a type!
if you want a union of values, index is the way.
Oh also that’s the point of the test type, to let keyof and index work their magic. The issue is my implementation of this aint working. I need help with it.

1 Like

wait so for your function definition are you tryna do smth like this?

function something<R extends keyof test>(a: R): test[R]

and then you want to return the type?

1 Like

I guess!
you know unity’s GetComponent? I kinda want something like that.
here’s my imaginary signature:

function something<R>(a: the type name of R) -> R
1 Like

I will refer you to this thread, it is a pearl for working with the new solver. It is hard to find information about how to use the new solver due to how new (and still incomplete) it is

What you will need is probably definitely type functions, however, I do not know how to apply them to a function in such a way that the return type depends on the input type. I was however able to apply the type function to a simple variable, depending on the string

Code
--!strict

type SomeTypeAlias = {
	a : number,
	b : number,
}

type function TypeFunction(Type : type)
	if Type:value() == "Test1" then
		return types.string
	elseif Type:value() == "Test2" then 
		return SomeTypeAlias
	else 
		error("Invalid type")
	end
end

local a : TypeFunction<"Test2">

(Note that type functions can now return type aliases, which wasn’t the case at the time of this reply)

1 Like

̶i̶ ̶t̶h̶i̶n̶k̶ ̶t̶h̶i̶s̶ ̶g̶u̶y̶’̶s̶ ̶m̶o̶r̶e̶ ̶(̶a̶ ̶l̶o̶t̶ ̶m̶o̶r̶e̶)̶ ̶k̶n̶o̶w̶l̶e̶d̶g̶e̶a̶b̶l̶e̶ ̶t̶h̶a̶n̶ ̶m̶e̶.̶.̶.̶ ̶i̶’̶v̶e̶ ̶t̶r̶i̶e̶d̶ ̶a̶ ̶f̶e̶w̶ ̶t̶h̶i̶n̶g̶s̶ ̶-̶ ̶e̶v̶e̶r̶y̶t̶h̶i̶n̶g̶ ̶t̶h̶a̶t̶ ̶i̶ ̶c̶a̶n̶ ̶t̶h̶i̶n̶k̶ ̶o̶f̶ ̶a̶t̶ ̶t̶h̶e̶ ̶m̶o̶m̶e̶n̶t̶ ̶b̶u̶t̶ ̶n̶o̶t̶h̶i̶n̶g̶ ̶w̶o̶r̶k̶s̶.̶.̶.̶ ̶s̶o̶r̶r̶y̶ ̶m̶a̶n̶

wait what if you use overloads?

function something(a: "number"): number
function something(a: "string"): string
function something(a: "Instance"): Instance

its really tedious but i think it works

̶h̶o̶l̶ ̶u̶p̶ ̶t̶h̶i̶s̶ ̶m̶i̶g̶h̶t̶ ̶b̶e̶ ̶t̶h̶e̶ ̶a̶n̶s̶w̶e̶r̶?̶!̶ ̶t̶r̶y̶ ̶t̶h̶i̶s̶:̶

local function something(a: "number"): number
	return a
end
local function something(a: "string"): string
	return a
end
local function something(a: "Part"): Part
	return a
end

local g = something("Part")
g.Pos

̶g̶e̶t̶ ̶p̶o̶s̶i̶t̶i̶o̶n̶ ̶t̶o̶ ̶a̶u̶t̶o̶c̶o̶m̶p̶l̶e̶t̶e̶ ̶f̶o̶r̶ ̶y̶o̶u̶

edit: im genuinely ■■■■■■■■

That’s not how it works, luau doesn’t support function overloading like java or other languages. What is happening here is the something function is being overwritten every time you redefine it, and the last time you define it, is the one that returns Part, which is why you are getting autocomplete for position

However, there is this section that talks about a way to do function overloading for types

I don’t think the “easy” way to do it works, because it only works for different types, and not different values of types (aka specific strings), but it could be possible to make a type function that constructs an “overloaded function” using type intersections, and creating specific strings types using types.singleton("WhateverTheStringIs")

1 Like

I cannot figure out how to make this work because the problem is more or less with generics than anything else. In my original example, the generic R ruins the input union to make the output work. My goal is to make the input union correctly work AND output value.

1 Like

oh… yeah im stupid :sob::pray:

The problem is with how Luau infers string literals as the type string, not as a string literal type. You’re annotations actually do work, but only when you explicitly cast the arguments.

-- a is string, index<test, string> is error
local x = something("number")

-- a is "number", index<test, "number"> is number
local y = something("number" :: "number")

Even with generic constraints, this won’t be possible until the inference behavior changes.

1 Like

yea, my issue though is because intersectioning R with the keyof ruins input type inference. I want to be able to infer input while also being able to infer output