typescript - Guard de tip generic pentru enum
Pot să scriu un protecție de tip non-generic pentru a verifica dacă un șir dat este membru al unui enum de șiruri astfel:
enum MyEnum {
Thing1 = 'thing one',
Thing2 = 'thing two',
}
const isMyEnum = (token: any): token is MyEnum => {
return Object.values(MyEnum).includes(token as MyEnum);
};
Este posibil să facem acest lucru generic, astfel încât să pot reutiliza aceeași logică de verificare pentru multe enum-uri de șiruri diferite?
Răspuns #1
Vrei să spui așa?
const isSomeEnum = <T>(e: T) => (token: any): token is T[keyof T] =>
Object.values(e).includes(token as T[keyof T]);
DeciisSomeEnum produce funcții de tip guard din obiecte enum. Tipul T[keyof T] înseamnă tipurile valorilor proprietăților din T.
const isMyEnum = isSomeEnum(MyEnum);
// const isMyEnum: (token: any) => token is MyEnum
Când apelezi isSomeEnum(MyEnum), tipul T este dedus ca typeof MyEnum, iar apoi T[keyof T] sunt valorile proprietăților acestuia, care este MyEnum.
Sper că asta ajută. Mult noroc!
Link către cod
Răspunsul #2
Enumurile de tip string și enumurile de tip number din TS generează cod JS foarte diferit.
Răspunsul acceptat funcționează pentru cazul OP-ului cu enumuri de tip șir.
Dar cineva care folosește enumerații numerice ar putea crede naiv că va funcționa și pentru cazul lor. Fiți atenți.
//number enum here
enum E {
A,
B,
C,
}
const isSomeEnum = <T>(e: T) => (token: any): token is T[keyof T] =>
(Object as any).values(e).includes(token as T[keyof T]);
console.log(isSomeEnum(E)("A")); //expected false, actual true
console.log(isSomeEnum(E)(0)); //expected true , actual true
function isSomeEnum2<T> (e: T) : (token: unknown) => token is T[keyof T] {
const keys = Object.keys(e)
.filter((k) => {
return !/^\d/.test(k);
});
const values = keys.map((k) => {
return (e as any)[k];
});
return (token: unknown): token is T[keyof T] => {
return values.includes(token);
};
};
console.log(isSomeEnum2(E)("A")); //expected false, actual false
console.log(isSomeEnum2(E)(0)); //expected true , actual true
Teren de joacă
