Skip to content

Instantly share code, notes, and snippets.

@nopeless
Last active January 15, 2026 17:21
Show Gist options
  • Select an option

  • Save nopeless/b3d5dc5f76dd969b2d18a95eb268fab5 to your computer and use it in GitHub Desktop.

Select an option

Save nopeless/b3d5dc5f76dd969b2d18a95eb268fab5 to your computer and use it in GitHub Desktop.
Add three.js type inference without having to rewrite into typescript at all + add typescript support

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "lib": [
      "dom",
      "es2015"
    ],
    "allowJs": true,
    "checkJs": false,
    "strict": false,
    "noImplicitAny": false,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "noEmit": true
  },
  "include": [
    "**/*"
  ],
  "exclude": [
    "node_modules",
    "**/lib"
  ]
}

we exclude lib files from being added because the prof uses lib file as including three.js (WHY???)

types.d.ts

import * as three from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

declare global {
  var THREE: typeof three;
}

declare module "three" {
  export { OrbitControls as OrbitAndPanControls };
}

run these commands

npm i -D typescript @types/three

tw.d.ts

declare module "tw" {
  export namespace TW {
    export const REVISION: string;
    
    /** To turn on debugging output, set this: */
    export let debug: boolean;

    // Colors
    
    /** Standard color */
    export const WHITE: number;
    /** Standard color */
    export const SILVER: number;
    /** Standard color */
    export const GRAY: number;
    /** Standard color */
    export const BLACK: number;
    /** Standard color */
    export const RED: number;
    /** Standard color */
    export const MAROON: number;
    /** Standard color */
    export const LIME: number;
    /** Standard color */
    export const GREEN: number;
    /** Standard color */
    export const BLUE: number;
    /** Standard color */
    export const NAVY: number;
    /** Standard color */
    export const YELLOW: number;
    /** Standard color */
    export const OLIVE: number;
    /** Standard color */
    export const FUCHSIA: number;
    /** Standard color */
    export const MAGENTA: number;
    /** Standard color */
    export const PURPLE: number;
    /** Standard color */
    export const AQUA: number;
    /** Standard color */
    export const CYAN: number;
    /** Standard color */
    export const TEAL: number;
    /** Standard color */
    export const ORANGE: number;

    /**
     * Input values are in 0-1; return value is a 24-bit number.
     * debug arg is optional, defaults to false.
     * You can give the return value to THREE.js functions, as the value of
     * color, ambient, and specular.
     * to determine the hex code, just do val.toString(16).
     * You might have to add a leading zero.
     */
    export function makeColor(r: number, g: number, b: number, debug?: boolean): number;
    
    /**
     * Returns a new dictionary with every key in the second dictionary,
     * overridden by keys from the first dictionary.
     */
    export function combineDictionaries(dic: any, defaults: any): any;
    
    /**
     * Transforms x, which in the range [minx, maxx] to y in the range
     * [miny, maxy].
     */
    export function linearMap(x: number, minx: number, maxx: number, miny: number, maxy: number): number;

    /** Keyboard callbacks. We have an array that maps from a keycode to a function that is invoked. */
    export const keyboard_callbacks: { [key: number]: Function };
    export const keyboard_callbacks_docs: { [key: number]: string };

    /**
     * Normally, keyboard callbacks depend on the canvas, so you should
     * call this after setting up the camera. If 'shared' is true, a
     * callback is set in the TW arrays that all canvases get a copy of.
     * 
     * The first argument is a one-character string that defines the key you want to bind.
     * The second argument is a function object.
     * The third argument is the documentation string that is displayed if the user presses the question mark key (?).
     */
    export function setKeyboardCallback(charstring: string, callback: Function, doc: string, shared?: boolean): void;
    
    /** Shows the available keyboard callbacks. */
    export function showKeyboardCallbacks(): void;
    
    /** Records the last element that was clicked on. */
    export let lastClickTarget: HTMLElement | null;
    
    /** The color that the canvas is cleared to, in camera setup. A light gray. */
    export let clearColor: number;

    /**
     * Initializes the TW stuff for a canvas. Adds the canvas to the
     * document, defaulting to the end of the body, but you can also give
     * a parent element by putting {parent: <domElt>} in the inits
     * object. This function also sets up keyboard callbacks. Returns the
     * canvas.
     */
    export function mainInit(renderer: import("three").WebGLRenderer, scene: import("three").Scene, inits?: { parentID?: string, parent?: HTMLElement, axisLength?: number }): HTMLCanvasElement;
    
    export interface BoundingBox {
        minx: number; maxx: number;
        miny: number; maxy: number;
        minz: number; maxz: number;
    }

    /** True if the bounding box has the necessary properties, all numbers, and min < max. */
    export function isValidBB(bb: any): boolean;
    
    export interface CameraParams {
        xSize: number;
        ySize: number;
        zSize: number;
        center: import("three").Vector3;
        fovyRadians: number;
        sceneDiameter: number;
        sceneRadius: number;
        cameraRadius: number;
        near: number;
        far: number;
    }

    /**
     * Return an object with a bunch of properties useful for setting
     * up a camera that can orbit around a scene without cutting
     * through it.
     */
    export function cameraSetupParams(sceneBoundingBox: BoundingBox, fovy: number): CameraParams;
    
    /** Checks camera parameters for validity. */
    export function checkCameraShapeParameters(fov: number, ar: number, near: number, far: number): void;
    
    /** Computes the bounding box of an object. */
    export function objectBoundingBox(object: import("three").Object3D): BoundingBox;

    export interface TWState {
        renderer: import("three").WebGLRenderer;
        scene: import("three").Scene;
        sceneBoundingBox: BoundingBox;
        cameraParams: CameraParams;
        cameraObject: import("three").Camera;
        render: () => void;
        cameraControls?: any; // OrbitControls
        axisHelper?: import("three").AxesHelper;
        sceneBoundingBoxHelper?: import("three").Mesh;
        ground?: import("three").Mesh;
        keyboard_callbacks: { [key: number]: Function };
        keyboard_callbacks_docs: { [key: number]: string };
    }

    /**
     * Sets up a camera for you, based on a scene bounding box (scene_bb),
     * an object with six properties: minx, maxx, miny, maxy, minz,
     * maxz.
     */
    export function cameraSetup(renderer: import("three").WebGLRenderer, scene: import("three").Scene, scene_bb: BoundingBox, inits?: { fovy?: number }): TWState;
    
    /** A synonym for cameraSetup, with a more ambiguous name. (Obsolete) */
    export function camera(renderer: import("three").WebGLRenderer, scene: import("three").Scene, scene_bb: BoundingBox, inits?: { fovy?: number }): void;

    /** Renders the scene using the state stored in the last click target. */
    export function render(): void;
    
    /** Toggles the visibility of the axis helper. */
    export function toggleAxes(mode?: string): void;
    
    /** Toggles the visibility of the bounding box helper. */
    export function toggleBoundingBox(mode?: string): void;
    
    /** Toggles the visibility of the ground plane. */
    export function toggleGroundPlane(mode?: string): void;
    
    /**
     * Keyboard event handler.
     * Use like: document.addEventListener('keypress',TW.onkeypress);
     */
    export function onkeypress(e: KeyboardEvent): void;
    
    /** Useful for turning some geometry into a mesh just for demo/debugging purposes. */
    export function createMesh(geom: import("three").BufferGeometry | any): import("three").Group; 
    
    /** Creates a sphere mesh at a given point with a given size. */
    export function makeSphereAt(pt: import("three").Vector3, size?: number): import("three").Mesh;
    
    /** Converts degrees to radians. */
    export function degrees2radians(degrees: number): number;
    
    /** Converts radians to degrees. */
    export function radians2degrees(radians: number): number;
    
    /** Computes the hypotenuse of a right triangle given an angle and the length of the opposite side. */
    export function hypotenuseOf(side: number, angle: number): number;

    /** Adds two triangles to the geometry to form a quad face. */
    export function addQuadFace(geom: any, a: number, b: number, c: number, d: number): void;
    
    /** Sets the material index for a list of faces. */
    export function setMaterialForFaces(geom: any, materialIndex: number, ...faceIndexes: number[]): void;
    
    /** Sets all face material indexes to the corresponding material, 1:1. */
    export function setMaterialForFaces11(geom: any): void;
    
    /** Returns a randomly generated color. */
    export function randomColor(): import("three").Color;
    
    /** Computes face colors based on vertex colors (for Geometry, not BufferGeometry). */
    export function computeFaceColors(geom: any): void;

    /** Adds an AxisHelper with given dimensions to the scene. It's initially invisible. */
    export function addAxisHelper(scene: import("three").Scene, lineLength: number, lineWidth: number): void;
    
    /** Color for the scene bounding box helper. */
    export const sceneBoundingBoxColor: number;
    
    /** This function creates a bounding box that the user set up the camera with. */
    export function addSceneBoundingBoxHelper(scene: import("three").Scene): void;
    
    /** Color for the ground plane. */
    export const groundColor: number;
    
    /** Add the ground mesh to the scene, though initially invisible. */
    export function addGroundHelper(scene: import("three").Scene, bb: BoundingBox): void;

    /** Sets the camera to look at the scene from +Z relative to it. */
    export function viewFromFront(): void;
    
    /** Sets the camera to look at the scene from +X relative to it. */
    export function viewFromSide(): void;
    
    /** Sets the camera to look at the scene from +Y relative to it. */
    export function viewFromAbove(): void;
    
    /** Sets the camera to look at the scene from +XYZ relative to it. */
    export function viewFromAboveFrontSide(): void;

    /** Create the geometry of a barn, given width, height and length (depth). */
    export function createBarn(width: number, height: number, length: number): import("three").BufferGeometry;
    
    export interface Vertex {
        pos: number[];
        norm: number[];
        uv: number[];
        color?: number[];
    }

    /** Sets buffer geometry attributes from an array of vertex objects. */
    export function setBufferGeometryFromVertices(geometry: import("three").BufferGeometry, vertices: Vertex[]): import("three").BufferGeometry;
    
    /** Sets buffer geometry attributes including colors from an array of vertex objects. */
    export function setBufferGeometryFromVerticesColors(geometry: import("three").BufferGeometry, vertices: Vertex[]): import("three").BufferGeometry;
    
    /** Creates a cube geometry with specific vertex attributes. */
    export function cubeGeometry(): import("three").BufferGeometry;
    
    /** Creates a barn geometry (BufferGeometry) without faces/material groups. */
    export function barnGeometry(width: number, height: number, depth: number): import("three").BufferGeometry;
    
    /** Creates a barn geometry with material groups/faces. */
    export function barnGeometryWithMaterialGroups(width: number, height: number, depth: number): import("three").BufferGeometry;

    /** Returns info about geometry (old style). */
    export function geometryInfoOld(geometry: import("three").BufferGeometry): any;
    
    /** Returns info about geometry. */
    export function geometryInfo(geometry: import("three").BufferGeometry): any;
    
    /** Prints geometry info to console and returns string. */
    export function printGeometryInfo(gi: any): string;
    
    /** Compares two geometries and logs differences. */
    export function compareGeometry(g1: import("three").BufferGeometry, g2: import("three").BufferGeometry): void;

    /** Returns a Mesh object that shows a wireframe barn. */
    export function wireBarnMesh(width: number, height: number, depth: number): import("three").LineSegments;
    
    /** Simple function to create and return a solid-colored wireframe cube. */
    export function wireCube(color: import("three").Color | string | number): import("three").Mesh;
    
    /** Simple function to create and return a solid-colored barn. */
    export function createBarnSolidColor(width: number, height: number, depth: number, color: import("three").Color | string | number): import("three").Mesh;
    
    /** Returns a mesh for a color cube, ready to add to a scene. */
    export function createColorCube(): import("three").Mesh;

    /** Creates and returns an HSL pyramid with the lightness axis coinciding with the Z axis. */
    export function createHSLPyramid(numWedges: number, apex: number): import("three").Mesh;
    
    /** A synonym for createHSLPyramid. */
    export function createHLSPyramid(numWedges: number, apex: number): import("three").Mesh;
    
    /** Returns a human-readable string representation of the 4x4 matrix. */
    export function matrix4x4toString(matrix: import("three").Matrix4 | import("three").Object3D, epsilon?: number): string;
    
    /** Creates a frustum visualization based on FOV. */
    export function createFrustumFOV(fovy: number, aspectRatio: number, near: number, far: number): import("three").LineSegments;
    
    /** Returns a THREE.Line object representing a frustum. */
    export function createFrustum(left: number, right: number, top: number, bottom: number, near: number, far: number): import("three").LineSegments;

    /** Returns an object with properties set for all the TeddyBear parameters. */
    export class TeddyBearParams {
        wireframe: boolean;
        sphereDetail: number;
        cylinderDetail: number;
        nose: boolean;
        noseRadius: number;
        noseRotation: number;
        ears: boolean;
        earRadius: number;
        earScale: number;
        earAngle: number;
        eyes: boolean;
        eyeRadius: number;
        eyeAngleX: number;
        eyeAngleY: number;
        arms: boolean;
        armLength: number;
        armRadiusTop: number;
        armRadiusBottom: number;
        legs: boolean;
        legRadiusTop: number;
        legRadiusBottom: number;
        legLength: number;
        legRotationX: number;
        legRotationZ: number;
        hipWidth: number;
        hipHeight: number;
        head: boolean;
        headRadius: number;
        bodyRadius: number;
        bodyScaleY: number;
        bodyColor: string;
        headColor: string;
        bodyMaterial: import("three").Material;
        headMaterial: import("three").Material;
        blackMaterial: import("three").Material;
        shoulderWidth?: number;
        shoulderHeight?: number;
    }

    /** Creates and returns the complete teddy bear, a mesh, with many attributes specified by params. */
    export function createTeddyBear(params: TeddyBearParams): import("three").Object3D;
    
    export interface ClickInfo {
        mx: number; my: number;
        cx: number; cy: number;
        winXSize: number; winYSize: number;
        x: number; y: number;
    }

    /** Converts mouse position to Normalized Device Coordinates (NDC). */
    export function convertMousePositionToNDC(event: MouseEvent | any): ClickInfo;
    
    /** Remember the last canvas clicked on. */
    export function storeClickTarget(event: MouseEvent | any): void;
    
    /** Returns 2^exponent for exponents between 1 and 31. */
    export function power2(exponent: number): number;
    
    /** Returns the next higher power of two. */
    export function nextPowerOf2(x: number): number;
    
    /** Returns an array containing a grayscale checkerboard pattern. */
    export function createCheckerboardGray(log2size: number): Uint8Array;
    
    /** Returns an array containing an RGB checkerboard pattern. */
    export function createCheckerboardRedWhite(log2size: number): Uint8Array;
    
    /** Checks if an object appears to be a 2D array (flattened) with width and height properties. */
    export function isArray2D(array2D: any): boolean;
    
    /** Accesses element in row i, column j of a 2D array. */
    export function rowMajorAref(array2D: any, i: number, j: number): number;
    
    /** Sets element in row i, column j of a 2D array. */
    export function rowMajorAset(array2D: any, i: number, j: number, val: number): void;
    
    /** Returns an array containing a grayscale USFlag pattern. */
    export function createUSFlagGray(log2size: number): Uint8Array;
    
    /** Returns a hex string representation of a byte array. */
    export function hexString(byteArray: Uint8Array | number[], width: number, height: number): string;
    
    /** Formats a string to a rectangular block. */
    export function rectangularString(str: string, width: number, height: number): string;
    
    /** Checks if an object appears to be an RGB array. */
    export function isArrayRGB(arrayRGB: any): boolean;
    
    /** Accesses element in row i, column j of a 2D RGB array. */
    export function rowMajorArefRGB(arrayRGB: any, i: number, j: number): [number, number, number];
    
    /** Sets element in row i, column j of a 2D RGB array. */
    export function rowMajorAsetRGB(arrayRGB: any, i: number, j: number, R: number, G: number, B: number): void;
    
    /** Returns an array containing a red, white and blue USFlag pattern. */
    export function createUSFlagRedWhiteBlue(log2size: number): Uint8Array;
    
    /** Creates a 2x2 texture from colors. */
    export function make2x2texture(colors: (string | number | import("three").Color)[]): import("three").DataTexture;
    
    /** Simple 2x2 image with spots of white, red, green and blue. */
    export function makeWRGBimage(): import("three").DataTexture;
    
    /** Returns an array containing a tricolor flag like the French flag. */
    export function createTriColorFlag(log2size: number, colorLeft: any, colorMiddle: any, colorRight: any): Uint8Array;
    
    /** Creates a texture as an array, then creates and returns an THREE.DataTexture. */
    export function makeFlagTexture(nickname: string): import("three").DataTexture;
    
    /** Returns a string printing most of the interesting information about a geometry. */
    export function stringifyGeometry(geom: any): string;
    
    /** Returns an array of 'numColors' different colors. */
    export function createDifferentColors(numColors: number): import("three").Color[];
    
    /** Takes a geometry and a selector for a DOM element and makes each face a different color. */
    export function showFaces(geom: any, domSelector: string): import("three").Mesh;
    
    /** Clever way to check if an integer is a power of two. */
    export function isPowerOf2(x: number): boolean;
    
    /** Function to load an image from a URL, check its dimensions, create a texture and return it. (Obsolete) */
    export function textureMaterial(url: string): import("three").MeshPhongMaterial; // obsolete
    
    export const textureLoader: import("three").TextureLoader;
    
    /** Load a texture from a URL. */
    export function loadTexture(url: string, callback: (texture: import("three").Texture) => void): void;
    
    /** Loads all of an array of urls and invokes the callback with an array of textures when all are finished loading. */
    export function loadTextures(filenameArray: string[], callback: (textures: import("three").Texture[]) => void): Promise<void>;
    
    /** Using the given list of control points, returns a THREE.Geometry. */
    export function createBezierCurveOld(cpList: [number, number, number][], steps: number): any;
    
    /** Creates a Bezier curve geometry. */
    export function createBezierCurve(controlPoints: [number, number, number][], numPoints: number): import("three").BufferGeometry;
    
    /** Returns a mesh for a sphere of given radius and material at the given location. */
    export function createPoint(P: [number, number, number], radius?: number, material?: import("three").Material): import("three").Mesh;
    
    /** Returns the binomial coefficient for N choose K. */
    export function binomial(n: number, k: number): number;
    
    /** Returns the value of the Bernstein polynomial. */
    export function bernstein(n: number, i: number, t: number): number;
    
    /** Function that returns a function suitable as an argument to THREE.ParametricGeometry. */
    export function bicubicBezierFunction(controlPoints: any): (s: number, t: number, target: import("three").Vector3) => void;
    
    /** 
     * BezierSurfaceGeometry extends Geometry which might not exist in type definitions.
     * I was going to have this inherit from THREE.PlaneGeometry...
     */
    export class BezierSurfaceGeometry {
        constructor(controlPoints: any, sSegments: number, tSegments: number);
        parameters: { controlPoints: any, sSegments: number, tSegments: number };
        controlPoints: any;
        sSegments: number;
        tSegments: number;
        vertices: import("three").Vector3[];
        faces: any[];
        faceVertexUvs: any[];
        
        computeBezierSurfacePoints(): import("three").Vector3[];
        computeBezierSurfaceFaces(): void;
        computeFaceNormals(): void;
        computeVertexNormals(): void;
    }
    
    /** Scales a vector (array). */
    export function vscale(k: number, v: number[]): number[];
    
    /** Adds two vectors (arrays). */
    export function vadd(u: number[], v: number[]): number[];
    
    /** Subtracts vector v from u (arrays). */
    export function vsub(u: number[], v: number[]): number[];
    
    /** Returns the dot product of u and v. */
    export function dot(u: number[], v: number[]): number;
    
    /** Returns the cross product of u and v. */
    export function cross(u: number[], v: number[]): number[];
    
    /** Returns a vector perpendicular to u and in the plane defined by u and v. */
    export function perp1(u: number[], v: number[]): number[];
    
    /** Returns a vector perpendicular to u and in the plane defined by u and v, using the triple product expansion. */
    export function perp2(u: number[], v: number[]): number[];
    
    /** For using the THREE.js stuff (array to Vector3). */
    export function vec3(v: number[]): import("three").Vector3;
    
    /** Shows the vertex and fragment shaders for an object. */
    export function showShaders(sceneObject: import("three").Mesh): void;
    
    /** Shows the vertex and fragment shaders for an object. */
    export function showShaders2(sceneObject: import("three").Mesh): void;
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment