I have the next code:
interface IPeople {
id: number,
role: string
}
const peoples: IPeople[] = [
{
id: 1,
role: 'student'
},
{
id: 2,
role: 'teacher'
}
]
I need to get the type of string literals based on peoples roles:
type PeoplesRoles = 'student' | 'teacher'
Can i do it dinamically? Thanks
CodePudding user response:
You need to make peoples
array immutable so TS is able to infer all keys and values.
interface IPeople {
id: number,
role: string
}
const peoples = [
{
id: 1,
role: 'student'
},
{
id: 2,
role: 'teacher'
}
] as const;
type Peoples = typeof peoples;
// "student" | "teacher"
type PeoplesRole = Peoples[number]['role']
UPDATE
If
role
is optional ...
interface IPeople {
id: number,
role: string
}
const peoples = [
{
id: 1,
role: 'student'
},
{
id: 2,
}
] as const;
type Peoples = typeof peoples;
type ObtainRole<T> =
(T extends any
? (T extends { role: infer Role }
? Role
: never
)
: never
)
// "student"
type PeoplesRole = ObtainRole<Peoples[number]>
Why i have used T extends any
? - To distribute the union type. See docs
After union distribution, this line T extends { role: infer Role }
applies to every element.