1

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

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks, its work fine, but is possible to little change code. If role a optional parameter and one of object dont have it {id: 1,role: 'student'},{id: 2} ? Then get just "student". Thanks
@kofyohugna made an update

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.