I wonder how to make combined types in arrays. If the BaseScope is present it automatically grants all extension scopes, so they shouldn't be present in the array. Example cases:
type ExtensionScopes = "read" | "write" | "update" | "delete";
type BaseScopes = "products" | "categories";
// Should pass
const a: Scope = ["products"];
const b: Scope = ["categories", "products"];
const c: Scope = ["products:delete", "products:write", "categories:delete"];
const d: Scope = ["categories", "products:write"];
// Should fail
const e: Scope = ["products", "products:read"];
const f: Scope = ["products", "categories", "products:read"];
const g: Scope = ["categories", "categories:delete"];
So far I was only able to filter out one "baseScope" from all using something like this:
type FilteredScope<T extends BaseScopes> =
(T | `${Exclude<BaseScopes, T>}:${ExtensionScopes}` | Exclude<BaseScopes, T>)[]
| (`${T}:${ExtensionScopes}` | Exclude<BaseScopes, T> | `${Exclude<BaseScopes, T>}:${ExtensionScopes}`)[]
type Scope = FilteredScope<"products"> // Any merge with another FilteredScope<> will break it