type function function_types(f: type)
if not f:is("function") then
print(`type[{f}] is not a function`)
return types.singleton(nil)
end
local union = nil
local parameters = f:parameters()
local head = parameters.head
if not head then return types.singleton(nil) end
for _, h in head do
union = if union then types.unionof(union, h) else h
end
return union and union or types.singleton(nil)
end
type f<T...> = (T...) -> T...
type table_type = {v: number}
type parameters_types = function_types<f<number, table_type>>
local p: parameters_types = { v = 20 } -- OK
local p: parameters_types = "" -- Type Error: Expected this to be 'number | { v: number }', but got 'string'
BUT! it’s not clear why do you need type functions since this works without them:
type f<T...> = (T...) -> T...
type specialized_function = f<number, string>
local specialized_function: specialized_function = function(number: number, string: string): (number, string)
return number, string
end
specialized_function("2", 3) -- Type Error: Expected this to be 'number', but got 'string'
-- and also Type Error: Expected this to be 'string', but got 'number'
specialized_function(2, "3") -- OK
once you decide later change type of the specialized_function to
type specialized_function = f<string, number>
then more warnings appear (which is good because it’s about maintaining code):
local specialized_function: specialized_function = function(number: number, string: string): (number, string)
return number, string
end -- Type Error: Expected this to be
-- '(string, number) -> (string, number)'
-- but got
-- '(number, string) -> (number, string)';
-- this is because
-- * it returns the 1st entry in the type pack is `number` in the latter type and `string` in the former type, and `number` is not a subtype of `string`
-- * it returns the 2nd entry in the type pack is `string` in the latter type and `number` in the former type, and `string` is not a subtype of `number`
-- * it takes the 1st entry in the type pack is `number` in the latter type and `string` in the former type, and `number` is not a supertype of `string`
-- * it takes the 2nd entry in the type pack is `string` in the latter type and `number` in the former type, and `string` is not a supertype of `number`
specialized_function("2", 3) -- OK
specialized_function(2, "3") -- Type Error: Expected this to be 'string', but got 'number'
-- and Type Error: Expected this to be 'number', but got 'string'