typescript - Hur man deklarerar en delmängdsenum från en annan enum
Sedan finns koden:
enum all {
a = 'a',
b = 'b',
c = 'c',
}
// what I want enum
enum wanted {
c = 'c',
}
Jag vet att det finns några lösningar som
type wanted = Exclude<all, all.a | all.b> // type wanted = all.c
Men typ är annorlunda än enum, eftersom det inte är itererbart!
Svar #1
En enum är helt enkelt ett objekt vid körning. Till exempel, din enum all omvandlas till detta:
var all;
(function (all) {
all["a"] = "a";
all["b"] = "b";
all["c"] = "c";
})(all || (all = {}));
// Essentially equivalent to
const all = {a: 'a', b: 'b', c: 'c'}
Du kan därför använda all som vilket normalt JavaScript-objekt som helst. Det finns många olika sätt att välja/utelämna vissa egenskaper:
// ES2015 Destructuring
const {a, b, ...wanted} = all
// ES2019 Object.fromEntries
const wanted = Object.fromEntries(
Object.entries(all)
.filter(([key]) =>
key === 'c'
// or if you wanted to exclude instead
// !['a', 'b'].includes(key)
)
) as {c: 'c'}
Om du ville göra det sista exemplet mer typ-säkert, kunde du använda denna hjälpare:
const pick = <T extends Record<string, unknown>, K extends keyof T>(
obj: T,
keys: readonly K[]
): Pick<T, K> =>
Object.fromEntries(
Object.entries(obj).filter(([key]) =>
(keys as readonly string[]).includes(key)
)
) as Pick<T, K>
const wanted = pick(all, ['c'])
Eller kanske detta för att utelämna egenskaper istället:
const omit = <T extends Record<string, unknown>, K extends keyof T>(
obj: T,
keys: readonly K[]
): Omit<T, K> =>
Object.fromEntries(
Object.entries(obj).filter(([key]) =>
!(keys as readonly string[]).includes(key)
)
) as Omit<T, K>
const wanted = omit(all, ['a', 'b'])
I TypeScript kan typer ha samma namn som värden, så om du ville att wanted också skulle vara en typ (precis som om du hade skrivit ut enumen), kunde du definiera en typ wanted med Exclude eller Pick (som i ditt exempel).
Lekplatslänk
Svar #2
Jag hittar faktiskt en lösning för att slå ihop enum
enum Mammals {
Humans = 'Humans',
Bats = 'Bats',
Dolphins = 'Dolphins'
}
enum Reptiles {
Snakes = 'Snakes',
Alligators = 'Alligators',
Lizards = 'Lizards'
}
export const Animals = { ...Mammals, ...Reptiles };
export type Animals = typeof Animals;
Så att du kan importera Animals och använda det som en enum.
