I'm using asserts condition and have a code like this
enum Types { a = "a", b = "b", c = "c" }
type Entity = { type: Types };
assert(condition: any): asserts condition {
if(!condition) throw new Error();
}
function abc(entity: Entity) {
assert(entity.type === Types.a || entity.type === Types.b);
...
}
function def(entity: Entity) {
assert(entity.type === Types.b || entity.type === Types.c);
...
}
function ghi(entity: Entity) {
assert(entity.type === Types.c);
...
}
Is it possible to make compact generic assertion function to use like this and get the same assertion type checks?
assertType(entity, [Types.a, Types.b]);
Answers to this question gave me an idea of solution.
function checkObjectType<
T extends { type: unknown },
X,
Y = never,
Z = never
>(obj: T, types: readonly [X, Y?, Z?]): obj is S & { type: X | Y | Z } {
return types.some((type) => type === obj.type;
}
// Then I can write code like this.
function abc(entity: Entity) {
assert(checkObjectType(entity, [Types.a, Types.b] as const));
...
// in Runtime we check assertion and get only types a and b here
// in Compiletime TS knows that only types a and b can be expected here
}