[Typescript] Tips: Turn a module into a type
Want to turn a module into a type? You can use typeof import('./')
to grab the type of any module, even third-party ones.
Here, we create a type from a constants.ts
file, then map over the values to create a union.
For example we have a constants.ts
:
export const ADD_TODO = "ADD_TODO";
export const EDIT_TODO = "EDIT_TODO";
export const REMOVE_TODO = "REMOVE_TODO";
Instead of doing as such: types.ts
export type Action = 'ADD_TODO' | 'EDIT_TODO' | 'REMOVE_TODO';
We want to dynamic approach:
export type ActionModule = typeof import('./constants');
export type Action = ActionModule[keyof ActionModule];
This example deps on how you name your "Re-export":
types/chat.ts:
export const SUBTYPE = {
UP: "up",
CONNECTED: "connected",
LOADING: "loading",
UNLOAD: "unload",
} as const;
export const TYPE = "chat";
types/devtools.ts:
export const TYPE = "devtools";
export const SUBTYPE = {
OPEN: "open",
} as const;
types/index.ts
export * as chat from "./chat"; // naming is important, as chat should the same as const TYPE = "chat"
export * as devtools from "./devtools";
index.ts:
import { chat, devtools } from "./types/index";
export type ActionModule = typeof import("./types/index");
export type Action = ActionModule[keyof ActionModule];
function sendMessage<K extends Action["TYPE"], U extends ActionModule[K]["SUBTYPE"]>(
dataType: K,
subtype: U[keyof U]
) {}
sendMessage(chat.TYPE, chat.SUBTYPE.CONNECTED); // works
sendMessage(chat.TYPE, devtools.SUBTYPE.OPEN); // nope Argument of type '"open"' is not assignable to parameter of type '"up" | "connected" | "loading" | "unload"'.