Search code examples
typescripttypescript-genericsmapped-typestypescript3.8

Create a mapped type containing all the static properties of a class


Given the classes:

class EnumerationDTO {
  designation: string;
  id: number;
}

class ExecutionStatusDTO extends EnumerationDTO {
    static readonly open: ExecutionStatusDTO = { id: 0, designation: 'Open' };
    static readonly working: ExecutionStatusDTO = { id: 1, designation: 'Working' };
    static readonly waiting: ExecutionStatusDTO = { id: 2, designation: 'Waiting' };
    static readonly resting: ExecutionStatusDTO = { id: 3, designation: 'Resting' };
    static readonly escalated: ExecutionStatusDTO = { id: 4, designation: 'Escalated' };
    static readonly done: ExecutionStatusDTO = { id: 5, designation: 'Done' };
    static readonly removed: ExecutionStatusDTO = { id: 6, designation: 'Removed' };
}

I need to count how many times each instance of ExecutionStatusDTO appears in an array and save that count in an object of type:

type statusesCount: {
    done: number;
    escalated: number;
    open: number;
    removed: number;
    resting: number;
    waiting: number;
    working: number;
}

But statusesCount cannot be simply defined but mapped from ExecutionStatsDTO


Solution

  • Solution 1:

    type statusesCount = Partial<
      {
        -readonly [key in keyof typeof ExecutionStatusDTO]: number;
      }
    >;
    

    will give

    type statusesCount = {
        prototype?: number;
        done?: number;
        escalated?: number;
        open?: number;
        removed?: number;
        resting?: number;
        waiting?: number;
        working?: number;
    }
    

    Solution 2 (more convenient if using strictNullChecks):

    type statusesCount = {
        -readonly [key in keyof Omit<typeof ExecutionStatusDTO, keyof typeof Function>]: number;
    };
    

    will give

    type statusesCount = {
        open: number;
        working: number;
        waiting: number;
        resting: number;
        escalated: number;
        done: number;
        removed: number;
    }