[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"'.

 

posted @ 2022-10-15 20:27  Zhentiw  阅读(15)  评论(0编辑  收藏  举报