Home

Awesome

Typeh<img src="./images/title-logo.png" align="top" width="24px">le

Automatically generate TypeScript types and interfaces for all serializable runtime values.

English | 简体中文

Typehole is a TypeScript development tool for Visual Studio Code that automates creating static typing by bridging runtime values from your Node.js or browser application to your code editor. It's useful when you need types for an API response or want to figure out types for values coming from a JS module. <br/> <br/>

file

Installation

Install the Visual Studio Code - extension. No additional build tooling or compiler plugins are needed.

How does it work?

  1. Find an any / unknown value you need an interface for
const response = await axios.get("https://reddit.com/r/typescript.json");
const data /* any */ = response.data;
  1. Place the value inside a typehole by selecting an expression and opening the Quick Fix menu by pressing ⌘ + . (macOS) or ctrl + . (Windows) and selecting Add a typehole.
type RedditResponse = any; // Type placeholder inserted by the extension
const response = await axios.get("https://reddit.com/r/typescript.json");

const data: RedditResponse = typehole.t(response.data);
  1. Run your code either in a browser or in Node.js. Typehole runtime captures the value and sends it back to your code editor. The VSCode extension records the captured value, turns all the values from that typehole into an interface and inserts it into the same module.
interface RedditResponse {
  /* ✨ Actual fields and types are automatically generated ✨ */
}

const response = await axios.get("https://reddit.com/r/typescript.json");
const data: RedditResponse = typehole.t(response.data);
  1. Remove the typehole, and you're done. Typeholes are meant to be development-time only, so you shouldn't commit them. Typehole provides you with 2 commands for easy removal of typeholes.
interface RedditResponse {
  /* ✨ Actual fields and types are automatically generated ✨ */
}

const response = await axios.get("https://reddit.com/r/typescript.json");
const data: RedditResponse = response.data;

This plugin is still very experimental, so please expect and report issues.

Features

Values that can be automatically typed

All primitive values and values that are JSON serializable.

So all values you can receive as an HTTP request payload can be turned into an interface.

From 1.4.0 forward also Promises are supported. All other values (functions etc.) will be typed as any.

Commands

image

Extension Settings

SettingTypeDefaultDescription
typehole.runtime.autoInstallbooleantrueInstall Typehole runtime package automatically when the first typehole is added
typehole.runtime.projectPathstringProject directory where Typehole runtime should be installed
typehole.runtime.packageManagernpm | yarnnpmPackage manager to be used when installing the runtime
typehole.runtime.extensionPortnumber17341HTTP port for HTTP extension to listen for incoming samples
typehole.typeOrInterfaceinterface | typeinterfaceKeyword to be used for generated types

Runtime

Typehole runtime's job is to capture values in your code and to send them to the extension in a serialized format.

import typehole from "typehole";

// -> POST http://extension/samples {"id": "t", "sample": "value"}
typehole.t("value");

// -> POST http://extension/samples {"id": "t1", "sample": 23423.432}
typehole.t1(23423.432);

// -> POST http://extension/samples {"id": "t2", "sample": {"some": "value"}}
typehole.t2({ some: "value" });

Typeholes are identified by the method name of your typehole call. Call .t2() would give the hole an id "t2". The ids are there, so the extension knows from where the value is coming from in the code.

In most cases, you should use unique keys for all holes. However, if you wish to record values from many holes into the same type, you might use the same id.

In some cases, the extension might not be running on the same host as your code, and you want to configure the address where the runtime sends the values. Node.js application running inside of a Docker container is one such case. In most cases, however, you do not need to configure anything.

import typehole, { configure } from "typehole";

configure({
  extensionHost: "http://host.docker.internal:17341",
});

Available runtime settings

SettingTypeDefaultDescription
extensionHoststringhttp://localhost:17341The address in which the extension HTTP listener is running

Known Issues

Release Notes

[1.8.0] - 2023-03-14

Added

[1.7.0] - 2021-07-08

Added

[1.6.3] - 2021-06-20

Fixed

[1.6.2] - 2021-05-22

Fixed

[1.6.1] - 2021-05-22

Fixed

[1.6.0] - 2021-05-20

Added

[1.5.1] - 2021-05-18

Fixed

[1.5.0] - 2021-05-15

Added

Fixed

[1.4.1] - 2021-05-09

Fixed

Added

[1.4.0] - 2021-05-09

Added

[1.3.0] - 2021-05-08

Added

[1.1.0] - 2021-05-08

Added


Enjoy!