I'm trying to understand what it looks like to move from Enums to string literals.
One hanging up point is functions which take advantage of those keys.
For example, if I use enums, I might have something like:
enum Role {
Standard = "Standard",
Admin = "Admin",
}
type Standard = {
role: Role.Standard
name: string
age: number
}
type Admin = {
role: Role.Admin
name: string
securityLevel: "Normal" | "Elevated" | "High"
}
type Employee = Admin | Standard
Then, I write a helper function that does something based solely on the role:
function doSomething(role: Role){ /*...*/ )
In this case, I will almost surely be pulling the role from employee, but notably, I'm only passing a string into the function.
Is it possible to do this with string literals? The best I can get is to pass in an object that has the role on it:
type Standard = {
role: "Standard"
name: string
age: number
}
type Admin = {
role: "Admin"
name: string
securityLevel: "Normal" | "Elevated" | "High"
}
type Employee = Admin | Standard
function doSomething(e: Pick<Employee, "role">){
return e.role === "Admin"
}
doSomething({role: "Admin"}) // compiles
doSomething({role: "Executive"}) // doesn't compile
I'm looking for the way to write it as:
doSomething("Admin") // compiles
doSomething("Executive") // doesn't compile
Alternatively, if this is just not something that's ever needed ... I'd like to understand a bit better - I'm fairly confident I've used Enums as types in functions before.
Update A possible alternative would be to somehow extract the string literal and then use that in the definition of the types that make up Employee
, e.g.,
type RoleStrings = "Standard" | "Admin"
type Standard = {
role: /* what goes here to say it's the string "Standard" that's _tied_ to the type `RoleStrings`? */
name: string
age: number
}
type Admin = {
role: /* what goes here to say it's the string "Admin" that's _tied_ to the type `RoleStrings`? */
name: string
securityLevel: "Normal" | "Elevated" | "High"
}
If I could do that, then this becomes trivial:
function doSomething(role: RoleStrings){/*...*/)
Update 2
I think I have a solution that I like:
type RoleStrings = Employee['role']
function doSomething(role: RoleStrings){/*...*/}
This accomplishes my goal of deriving the allowable strings and ensuring that the for the function is as direct as possible without requiring an Employee
(even if it's a Pick
) object.
CodePudding user response:
You can use keyof typeof
to get the type that represents the union of keys:
function doSomething(role: keyof typeof Role){ /*...*/ }
If you don't want to use enum
at all, then you can just use a union:
function doSomething(role: "Standard" | "Admin"){ /*...*/ }
CodePudding user response:
Given:
type Standard = {
role: "Standard"
name: string
age: number
}
type Admin = {
role: "Admin"
name: string
securityLevel: "Normal" | "Elevated" | "High"
}
type Employee = Admin | Standard
The cleanest answer I've found is:
type RoleStrings = Employee['role']
function doSomething(role: RoleStrings){/*...*/}