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']
Playground
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.