Home > database >  What is the correct way to have dynamic keys that are string literal union?
What is the correct way to have dynamic keys that are string literal union?

Time:10-27

I want to define a type in TS where the key is dynamic, but it cannot be any old string. It must be one of the following values: 'TO_DO', 'IN_PROGRESS', or 'DONE'. So, for example, the data could look like this:

{columns: {
    TO_DO: {
        status: 'TO_DO',
        title: 'To do'
        taskIds: ['abc', 'def', 'ghi']
    },
    IN_PROGRESS: {
        status: 'IN_PROGRESS',
        title: 'In Progress'
        taskIds: ['qrs', 'tuv', 'xyz']
    }
}

This is what I did, but I don't know if it is correct:

export type Column = {
  status: 'TO_DO' | 'IN_PROGRESS' | 'DONE'
  title: 'To do' | 'In progress' | 'Done'
  taskIds: string[]
}

export type Columns = {
  [key in 'TO_DO' | 'IN_PROGRESS' | 'DONE']: Column
}

CodePudding user response:

If you're trying to make the status match the key, you can enforce a tighter contract using generics as follows:

export type Column<T extends string> = {
  status: T
  title: 'To do' | 'In progress' | 'Done'
  taskIds: string[]
}

export type Columns = {
  [key in 'TO_DO' | 'IN_PROGRESS' | 'DONE']: Column<key>
}

const data: Columns = {
    DONE: {
        status: "DONE",
        taskIds: [],
        title: "To do"
    },

    IN_PROGRESS: {
        status: "DONE", // error: type '"DONE"' is not assignable to type '"IN_PROGRESS"'.
        taskIds: [],
        title: "To do"
    }
}
  • Related