Union between 2 tables of the same interface should be able to be indexed
local interface BaseResult<TValue, TError> where self.ok
ok: boolean
unwrap: function(self): TValue
end
local record Ok<T> is BaseResult<T, any> where self.ok == true
value: T
end
local record Error<TError> is BaseResult<any, TError> where self.ok == false
error: TError
end
function Ok:unwrap(): T
return self.value
end
function Error:unwrap(): any
error("Called unwrap on an Error: "..tostring(self.error))
end
local type Result<TValue, TError> = Ok<TValue> | Error<TError>
local function divide(a: number, b: number): Result<number, string>
if b == 0 then
return err("Division by zero")
else
return ok(a / b)
end
end
local x = divide(10, 2):unwrap()
This currently fails with cannot index key 'unwrap' in type Result<number, string>
Union between 2 tables of the same interface
Those two types do not inherit the same interface. Ok inherits BaseResult<T, any> and Error inherits BaseResult<any, TError>. Those are clearly not the same type!
Union between 2 tables of the same interface
Those two types do not inherit the same interface.
OkinheritsBaseResult<T, any>andErrorinheritsBaseResult<any, TError>. Those are clearly not the same type!
In the case it is local type Result<TValue, TError> = Ok<TValue, TError> | Error<TValue, TError> (with proper adjustments to the interfaces) the issue still persists
local interface BaseResult<TValue, TError> where self.ok
ok: boolean
unwrap: function(self): TValue
end
local record Ok<T, TError> is BaseResult<T, TError> where self.ok == true
value: T
end
local record Error<T, TError> is BaseResult<T, TError> where self.ok == false
error: TError
end
function Ok:unwrap(): T
return self.value
end
function Error:unwrap(): T
error("Called unwrap on an Error: "..tostring(self.error))
end
local function ok<TValue, TError>(value: TValue): Ok<TValue, TError>
return { ok = true, value = value }
end
local function err<TValue, TError>(error: TError): Error<TValue, TError>
return { ok = false, error = error }
end
local type Result<TValue, TError> = Ok<TValue, TError> | Error<TValue, TError>
local function divide(a: number, b: number): Result<number, string>
if b == 0 then
return err("Division by zero")
else
return ok(a / b)
end
end
local x = divide(10, 2):unwrap()
IIRC, that happens because each is BaseResult<...> application of type variables in the record declaration produces a new (distinct) type.
What happens if the divide function returns BaseResult?
IIRC, that happens because each
is BaseResult<...>application of type variables in the record declaration produces a new (distinct) type.What happens if the
dividefunction returnsBaseResult?
that works, but then flow analysis works more annoyingly
local x = divide(10, 2)
if x is Ok<number> then
print(x.value)
else
print(x.err)
end
vs what id have to do
local x = divide(10, 2)
if x is Ok<number, string> then
print(x.value)
elseif x is Error<number, string> then
print(x.err)
end
its a kinda minor thing tbh