export type IsInArray = X extends A[number] ? true : false; export type HasUniqueItems = A extends readonly [ infer X, ...infer Rest, ] ? IsInArray extends true ? [false, "Encountered value with duplicates:", X] : HasUniqueItems : true; type TyEnum = { [Key in K]: Key; }; type TyStrToInd = { [Key in K]: number; }; type TyCoolEnum> = { asArr: Tuple; asObjEnum: Readonly>; asSet: Set; asStrToInd: Readonly>; }; // generate type-safe object (as enum) from array of strings export const createCoolEnum = < // prettier-ignore TupleInput extends ( number extends TupleInput["length"] ? `Should be as const` : HasUniqueItems> extends true ? Readonly : `Should have unique elements, found duplicate` ), Tuple extends Exclude, >( arrInput: TupleInput, ): TyCoolEnum => { const arr = arrInput as unknown as Tuple; const asSet = new Set(arr); if (asSet.size !== arr.length) { throw new Error("groupIdsArr should have unique elements"); } type TheObjEnum = TyEnum; const asObjEnum: TheObjEnum = arr.reduce((accu, curr) => { accu[curr] = curr; return accu; }, {} as Record) as TheObjEnum; type TheStrToInd = TyStrToInd; const asStrToInd: TheStrToInd = arr.reduce((accu, curr, index) => { accu[curr] = index; return accu; }, {} as Record) as TheStrToInd; const final: TyCoolEnum = { asArr: arr, asObjEnum, asSet, asStrToInd, }; return final; }; // test: // let jijdfdf = ["vbvvbvbbvb", "qeqeqeqe", "i7777", "i7777"] as const; // const qqdqd = createCoolEnum(jijdfdf); // const qqdqd2 = createCoolEnum(["dfdf", "bbbbb"]); // qqdqd.asObjEnum.i7777; // qqdqd2.asObjEnum.dfdf;