Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deprecating enum values without duplicating

Tags:

typescript

I have a enum like this:

enum Animals {
 WOLF = 'wolf',
 BADGER = 'badger',
 CAT = 'cat',
}

And I am deprecating CAT. Meaning objects in my DB can still have it on read of those objects, but you shouldn't be able to create a new object with CAT.

What I don't want is this:

enum AnimalsIn {
 WOLF = 'wolf',
 BADGER = 'badger',
}
enum AnimalsOut {
 WOLF = 'wolf',
 BADGER = 'badger',
 CAT = 'cat',
}

Is there a way to spread / extend AnimalsIn and have AnimalsOut only contain the deprecated enums? Or at least check if AnimalsOut has all the same enums that AnimalsIn, meaning check if it's a subset.

Ideally:

type AnimalsIn = Deprecate<AnimalsOut, 'CAT'>
like image 211
ThomasReggi Avatar asked May 17 '26 12:05

ThomasReggi


1 Answers

An enum is bot a value and a type, so it we are going to mimic the behavior of an enum we need to define both.

We can use the Omit type to exclude the members we no longer want:

enum AnimalsOut {
    WOLF = 'wolf',
    BADGER = 'badger',
    CAT = 'cat',
}

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> //probably in a lib already 
type DeprecateEnumObject<T, K extends keyof T> = Omit<T, K>
type DeprecateEnumValues<T, K extends keyof T> = DeprecateEnumObject<T, K>[Exclude<keyof T, K>]

type AnimalsIn = DeprecateEnumValues<typeof AnimalsOut, 'CAT'>
const AnimalsIn: DeprecateEnumObject<typeof AnimalsOut, 'CAT'> = AnimalsOut;

let a: AnimalsIn = AnimalsIn.BADGER;

This mostly works, what does not work is enum literal types, we can get to the type but its more convoluted:

let ai: AnimalsOut.BADGER = AnimalsIn.BADGER;
let ao: AnimalsIn.BADGER = AnimalsIn.BADGER;// error
let ao2: typeof AnimalsIn['BADGER'] = AnimalsIn.BADGER;// more convoluted 
like image 68
Titian Cernicova-Dragomir Avatar answered May 19 '26 02:05

Titian Cernicova-Dragomir