Ts-toolbelt: Reverse type for enums

Created on 15 Aug 2019  路  7Comments  路  Source: millsp/ts-toolbelt

馃崺 Feature Request

Describe the solution you'd like

I will be very cool to have a type that inverses a string enum type.
For example

enum Validations {
  J1 = 'NoComm',
  J2 = 'Normal',
  J3 = 'CreditLimit',
  J4 = 'AutoComm',
}

type ValidationsType = typeof Validations;
type ValidationsKeys = keyof ValidationsType;
type Minify<T> = {
  [K in keyof T]: T[K];
};

type ValidationsReverse: A.Compute<
  Minify<
    Union.IntersectOf<
      {
        [key in ValidationsKeys]: {
          [key2 in ValidationsType[key]]: key;
        };
      }[ValidationsKeys]
    >
  >
>;
/*
ValidationsReverse = {
  NoComm: "J1";
  Normal: "J2";
  CreditLimit: "J3";
  AutoComm: "J4";
*/

@pirix-gh what do you think?

feature

Most helpful comment

@regevbr, this seems to be good to me!

I can publish this tomorrow, here it is:

import {A, U, O} from 'ts-toolbelt';

enum E {
  A = 'Av',
  B = 'Bv',
  C = 'Cv',
  D = 'Dv',
}

type O = {
  A: 'Av'
  B: 'Bv'
  C: 'Cv'
  D: 'Dv'
}

type Invert<O extends O.Record<keyof O, string>> = 
  A.Compute<U.IntersectOf<
    { // swaps the key and the value
      [K in keyof O]: O.Record<O[K], K>
    }[keyof O]
>>

type t0 = Invert<typeof E>
type t1 = Invert<O>

Thanks, it's really a useful type you brought here

All 7 comments

The following works (enums needs to be computed first for some reason)

type Minify<T> = {
  [K in keyof T]: T[K];
};
type IndexType = string | number | symbol;
type Inverse<T extends Record<IndexType, IndexType>> = Minify<
  Union.IntersectOf<
    {
      [key in keyof T]: {
        [key2 in T[key]]: key;
      };
    }[keyof T]
  >
>;

For simple obects:

type t = A.Compute<
  Inverse<{
    A: 'B';
    C: 'D';
  }>
>;
/*
t = {
  B: "A";
  D: "C";
};
/*

For enums:

enum Validations {
  J1 = 'NoComm',
  J2 = 'Normal',
  J3 = 'CreditLimit',
  J4 = 'AutoComm',
}

type ValidationsReverse: A.Compute<Inverse<A.Compute<typeof Validations>>>; // Notice we must compute the typeof the enum for it to work
/*
ValidationsReverse = {
  NoComm: "J1";
  Normal: "J2";
  CreditLimit: "J3";
  AutoComm: "J4";
*/

This will also be useful to implement underscore`s invert method typing - https://underscorejs.org/#invert

@regevbr, this seems to be good to me!

I can publish this tomorrow, here it is:

import {A, U, O} from 'ts-toolbelt';

enum E {
  A = 'Av',
  B = 'Bv',
  C = 'Cv',
  D = 'Dv',
}

type O = {
  A: 'Av'
  B: 'Bv'
  C: 'Cv'
  D: 'Dv'
}

type Invert<O extends O.Record<keyof O, string>> = 
  A.Compute<U.IntersectOf<
    { // swaps the key and the value
      [K in keyof O]: O.Record<O[K], K>
    }[keyof O]
>>

type t0 = Invert<typeof E>
type t1 = Invert<O>

Thanks, it's really a useful type you brought here

@pirix-gh looks good!

How come your type is computed well and mine needed the Minify trick?

In O extends tObject.Record<keyof O, string> I think you should use your Index internal type here as it is a valid use case:

type Invert<O extends tObject.Record<keyof O, Index>> = A.Compute<
  Union.IntersectOf<
    {
      [K in keyof O]: tObject.Record<O[K], K>;
    }[keyof O]
  >
>;
const symb = Symbol(2);
type Obj = {
  A: 1;
  B: 'B';
  C: typeof symb;
};
type t3 = Invert<Obj>;

Yes, good point, thanks

It's out! I thanked you on the readme for your great devotion @regevbr :tada:

@pirix-gh thanks again! It works perfectly :-)

Was this page helpful?
0 / 5 - 0 ratings