--!strict
type Predicate<T> = {
Type: () -> T
}
type function Interface(shape)
local out = types.newtable()
for key, prop in shape:properties() do
out:setproperty(key, prop.read:readproperty(types.singleton("Type")):returns().head[1])
end
return out
end
local function makeStringPredicate(): Predicate<string>
return nil :: never
end
local function makeInterfacePredicate<T>(tbl: T): Predicate<Interface<T>>
return nil :: never
end
local function intersect<A, B>(a: Predicate<A>, b: Predicate<B>): Predicate<A & B>
return nil :: never
end
local a = makeInterfacePredicate({ a = makeStringPredicate() })
local b = makeInterfacePredicate({ b = makeStringPredicate() })
local intersection = intersect(a, b)
type IntersectionType = typeof(intersection.Type())
local bad: IntersectionType = {
a = 32, -- This gives me a warning, which is correct!
b = 91, -- This doesn't? But it should be the same as the one above
}
This appears to be a bug, but I wanted to confirm that I’m not misunderstanding something in my code.
I’m working on a runtime type-checking library and ran into an issue with intersections. Individually, the interface predicates seem to produce the correct types, but when I combine them through a generic, one side of the resulting table loses it’s property type checking.
In this example, I would expect both a and b to be checked as a string. Instead, only one side is enforced, while the other seems to get turned into unknown.
