Products

TypeScript Support

Jspreadsheet provides comprehensive TypeScript support with built-in type definitions, enabling developers to build type-safe spreadsheet applications. This guide covers TypeScript-specific features, type definitions, and best practices for integrating Jspreadsheet into TypeScript projects.

Documentation

Installation with Types

npm install jspreadsheet
# Types are included in the main package

Type-Safe Spreadsheet Creation

Create spreadsheets with full type safety:

import jspreadsheet, { SpreadsheetConfig, WorksheetInstance } from 'jspreadsheet';

// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('YjQ5MzQxMjQ3MGY0NzViOTM1N2E5YTQxZGY5OTNkMmY5ZWI1N2NlMWE2MjU3MGI1Mjg2YTQwYzU0YTljODY0MjkyMDRiYmQyYWViZDI4YzJiMjFhMzlkNzE5MWExMzliNmExYTRiZDFlZGMxMjMyZGI2NzRiNGU3NGQ4YWMxODgsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREkzTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

const config: SpreadsheetConfig = {
    worksheets: [{
        data: [
            ['Product', 'Price', 'Available'],
            ['Laptop', 999.99, true],
            ['Mouse', 29.99, false]
        ],
        columns: [
            { type: 'text', title: 'Product Name', width: 200 },
            { type: 'number', title: 'Price ($)', width: 100 },
            { type: 'checkbox', title: 'In Stock', width: 80 }
        ],
        minDimensions: [3, 10]
    }]
};

const spreadsheet: WorksheetInstance[] = jspreadsheet(document.getElementById('spreadsheet'), config);

Custom Cell Types with TypeScript

Create type-safe custom cell editors using imported types:

import jspreadsheet, { Editor, worksheetInstance, Column, Cell } from 'jspreadsheet';

// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('YjQ5MzQxMjQ3MGY0NzViOTM1N2E5YTQxZGY5OTNkMmY5ZWI1N2NlMWE2MjU3MGI1Mjg2YTQwYzU0YTljODY0MjkyMDRiYmQyYWViZDI4YzJiMjFhMzlkNzE5MWExMzliNmExYTRiZDFlZGMxMjMyZGI2NzRiNGU3NGQ4YWMxODgsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREkzTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

// Create a custom email cell type using the built-in Editor interface
const emailCellType: Editor = {
    createCell: (cell: HTMLTableCellElement, value: any, x: number, y: number, instance: worksheetInstance, options: Column | Cell) => {
        const input = document.createElement('input');
        input.type = 'email';
        input.value = value || '';
        input.classList.add('jss_input');
        input.style.width = '100%';
        input.style.border = 'none';
        input.style.outline = 'none';
        cell.appendChild(input);
        input.focus();
    },

    updateCell: (cell: HTMLTableCellElement, value: any, x: number, y: number, instance: worksheetInstance, options: Column | Cell) => {
        const input = cell.querySelector('input') as HTMLInputElement;
        if (input) {
            input.value = value || '';
        }
    },

    openEditor: (cell: HTMLTableCellElement, value: any, x: number, y: number, instance: worksheetInstance, options: Column | Cell) => {
        const input = cell.querySelector('input') as HTMLInputElement;
        if (input) {
            input.focus();
            input.select();
        }
    },

    closeEditor: (cell: HTMLTableCellElement, confirmChanges: boolean, x: number, y: number, instance: worksheetInstance, options: Column | Cell) => {
        const input = cell.querySelector('input') as HTMLInputElement;
        if (input && confirmChanges) {
            // Validate email format
            const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
            const isValid = emailRegex.test(input.value);

            if (!isValid && input.value.trim() !== '') {
                alert('Please enter a valid email address');
                return false; // Prevent saving invalid email
            }

            return input.value;
        }
        return '';
    },

    destroyCell: (cell: HTMLTableCellElement, x: number, y: number, instance: worksheetInstance) => {
        // Cleanup when cell is destroyed
        const input = cell.querySelector('input');
        if (input) {
            input.remove();
        }
    }
};

// Use the custom editor in a spreadsheet configuration
const config = {
    worksheets: [{
        data: [
            ['Name', 'Email'],
            ['John Doe', '[email protected]'],
            ['Jane Smith', '[email protected]']
        ],
        columns: [
            { type: 'text', title: 'Full Name', width: 200 },
            { type: emailCellType, title: 'Email Address', width: 250 }
        ]
    }]
};

const spreadsheet = jspreadsheet(document.getElementById('spreadsheet'), config);

Event Handling with TypeScript

Type-safe event handlers using imported types:

import jspreadsheet, { WorksheetInstance, SpreadsheetConfig } from 'jspreadsheet';

// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('YjQ5MzQxMjQ3MGY0NzViOTM1N2E5YTQxZGY5OTNkMmY5ZWI1N2NlMWE2MjU3MGI1Mjg2YTQwYzU0YTljODY0MjkyMDRiYmQyYWViZDI4YzJiMjFhMzlkNzE5MWExMzliNmExYTRiZDFlZGMxMjMyZGI2NzRiNGU3NGQ4YWMxODgsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREkzTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

// Use the built-in event handler types from Jspreadsheet
const config: SpreadsheetConfig = {
    worksheets: [{
        data: [
            ['Name', 'Age', 'City'],
            ['John', 30, 'New York'],
            ['Jane', 25, 'London']
        ],
        onchange: (worksheet: WorksheetInstance, cell: HTMLElement, x: number, y: number, value: any, oldValue: any) => {
            console.log(`Cell ${worksheet.getCellNameFromCoords(x, y)} changed from '${oldValue}' to '${value}'`);
        },
        onselection: (worksheet: WorksheetInstance, x1: number, y1: number, x2: number, y2: number) => {
            const range = worksheet.getRangeFromCoords(x1, y1, x2, y2);
            console.log(`Selected range: ${range}`);
        },
        onbeforechange: (worksheet: WorksheetInstance, cell: HTMLElement, x: number, y: number, value: any) => {
            // Type-safe validation
            if (typeof value === 'string' && value.length > 100) {
                alert('Text too long!');
                return false; // Prevent change
            }
            return value;
        }
    }]
};

// Create spreadsheet with type-safe event handlers
const spreadsheet: WorksheetInstance[] = jspreadsheet(document.getElementById('spreadsheet'), config);

Complete Type Definitions

For developers who want to explore all available interfaces and types, you can view the complete TypeScript definitions:

📄 View Complete Type Definitions

Framework Integration

React Application with File Loading

Complete React application example with TypeScript, demonstrating file loading, validations, and proper typing:

import React, { useRef } from "react";
import { Spreadsheet, Worksheet, jspreadsheet } from "@jspreadsheet/react";
import formula from "@jspreadsheet/formula-pro";
import parser from "@jspreadsheet/parser";
import render from "@jspreadsheet/render";

// Style dependencies
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";

// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('YjQ5MzQxMjQ3MGY0NzViOTM1N2E5YTQxZGY5OTNkMmY5ZWI1N2NlMWE2MjU3MGI1Mjg2YTQwYzU0YTljODY0MjkyMDRiYmQyYWViZDI4YzJiMjFhMzlkNzE5MWExMzliNmExYTRiZDFlZGMxMjMyZGI2NzRiNGU3NGQ4YWMxODgsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREkzTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');
// Load the extensions
jspreadsheet.setExtensions({ formula, parser, render });

export default function App() {
    // Properly type the spreadsheet ref
    const spreadsheet = useRef<jspreadsheet.worksheetInstance[]>();
    // Input ref for file loading
    const inputRef = useRef<HTMLInputElement>(null);

    // Get the root element
    const getRootElement = function() {
        if (spreadsheet.current) {
            return spreadsheet.current[0].parent.element;
        }
    }

    // Create the spreadsheet from a local file
    const load = function (e: React.ChangeEvent<HTMLInputElement>) {
        // Parse XLSX file and create a new spreadsheet
        if (jspreadsheet.parser && e.target.files) {
            jspreadsheet.parser({
                file: e.target.files[0],
                locale: "en-GB",
                onload: function (config) {
                    let root = getRootElement();
                    if (root) {
                        // Destroy the existing one first
                        jspreadsheet.destroy(root);
                        // Create a new spreadsheet from the file
                        jspreadsheet(root, config);
                    }
                },
                onerror: function (error) {
                    alert(error);
                },
            });
        }
    }

    // Custom event to remove all strings that start with #
    const afterChanges = function(worksheet: jspreadsheet.worksheetInstance, records: jspreadsheet.Record[]) {
        for (let i = 0; i < records.length; i++) {
            let x = records[i].x;
            let y = records[i].y;
            let record = worksheet.getCellObject(x, y);
            if (record.element && typeof(record.v) === 'string' && record.v.startsWith('#')) {
                // Clear what users see on the cell
                record.element.textContent = '';
            }
        }
    }

    // Custom event to show all worksheets
    const onload = function(spreadsheet: jspreadsheet.spreadsheetInstance) {
        for (let i = 0; i < spreadsheet.worksheets.length; i++) {
            spreadsheet.worksheets[i].openWorksheet();
            spreadsheet.worksheets[i].element.style.display = 'block';
        }
    }

    // Type-safe style configuration
    const style: string[] = [
        'background: yellow'
    ]

    // Type-safe column configuration
    const columns: jspreadsheet.Column[] = [
        { type: 'numeric' },
        { type: 'text' },
        {},
        { s: 0, mask: '@' },
    ]

    // Type-safe validation rules
    const validations: jspreadsheet.Validation[] = [
        {
            range: 'Sheet1!A1:A3',
            action: "warning",
            criteria: "<",
            type: "number",
            value: [500],
            text: 'Custom message about the number',
        },
        {
            range: 'Sheet1!B1:B3',
            action: "format",
            criteria: "<",
            type: "number",
            value: [75],
            format: { 'background-color': 'red' },
        },
        {
            range: 'Sheet1!B1:B3',
            action: "format",
            criteria: "<",
            type: "number",
            value: [50],
            format: { 'background-color': 'orange' },
        },
        {
            range: 'Sheet1!B1:B3',
            action: "format",
            criteria: "<",
            type: "number",
            value: [25],
            format: { 'background-color': 'green' },
        }
    ]

    const data = [
        ['007', '007', '007', '007'],
        ['', '49', ''],
        ['', '69', ''],
    ]

    return (
        <div>
            <Spreadsheet
                ref={spreadsheet}
                tabs={true}
                style={style}
                onload={onload}
                onafterchanges={afterChanges}
                validations={validations}
            >
                <Worksheet minDimensions={[4, 4]} columns={columns} data={data} />
                <Worksheet minDimensions={[4, 4]} columns={columns} />
            </Spreadsheet>
            <input
                ref={inputRef}
                id="file"
                type="file"
                name="file"
                onChange={load}
                style={{ display: "none" }}
            />
            <p>
                <input
                    type="button"
                    value="Load a XLSX file from my local computer"
                    onClick={() => inputRef.current!.click()}
                />
            </p>
        </div>
    );
}

More Examples

You can use TypeScript with Jspreadsheet in any of your favorite frameworks: