Home > Blockchain >  How to set every constant variable value in a file as a type?
How to set every constant variable value in a file as a type?

Time:08-26

I want to set a type for an object and I want to set it to any of the variables values inside types.ts :

export const INIT = "INIT";
export const LOGIN = "LOGIN";

I want to say the type can be any of the variables values in the types.ts :

import { LOGIN, INIT } from "./types";

interface Action {
  type: typeof INIT | typeof LOGIN;
}

export const reducer = (state = initialState, action: Action) => {
  switch (action.type) {
    case LOGIN:
      return {
        state,
      };
  }
};

Is there anyway I can tell typescript to map all the constant variables inside types.ts and set all of their values as a type at once and not setting typeof each of them everytime a new constant I add in the types.ts ?

CodePudding user response:

You can accomplish this by using a namespace import statement for all of your exported constant values. See comments in the code below:

./constants.ts:

export const INIT = 'INIT';
export const LOGIN = 'LOGIN';

./module.ts:

/* Using a namespace import statement places all of the exports from
the './constants.ts' module on an object named `Constant`: */
import * as Constant from './constants';

/** A type utility to get a union of all types of values in an object type */
type Values<T> = T[keyof T];

/* This uses the same identifer as the imported value object Constant.
Because it's a type name, using the same name is ok — TS has no problems and it
makes the `Constant` identifier work like a string enum
in the scope of this module: */
type Constant = Values<typeof Constant>;
   //^? type Constant = "INIT" | "LOGIN"

type Action = {
  type: Constant;
//^? (property) type: "INIT" | "LOGIN"
};

/* You didn't show the initialState variable in your question, so here's
an example: */
type State = Record<'prop1' | 'prop2', string>;
   //^? type State = { prop1: string; prop2: string; }

const initialState: State = {
  prop1: 'hello',
  prop2: 'world',
};

const reducer = (state = initialState, action: Action) => {
  switch (action.type) {
    case Constant.LOGIN: return { state };
    // etc...
  }
};


Although a more modular pattern would be to do that in the constants module instead:

./constants.ts:

export const INIT = 'INIT';
export const LOGIN = 'LOGIN';

export const Constant = {
  INIT,
  LOGIN,
} as const;

type Values<T> = T[keyof T];
export type Constant = Values<typeof Constant>;

./module.ts:

import {Constant} from './constants';

type Action = {
  type: Constant;
//^? (property) type: "INIT" | "LOGIN"
};

// ... the remaining code is the same as the above example

  • Related