Skip to content

ASCII Table — TypeScript source

A searchable, filterable reference for all 128 ASCII code points. See the decimal, hex, octal, and binary form of every character, narrow to printable characters only, clamp the code-point range, and click any row to copy. Runs 100% client-side.

This is the TypeScript implementation — the same logic the interactive tool runs, in a shareable, citable form.

// Pure logic for the ASCII Table. No React, no DOM - the unit-test surface.
// Fully deterministic: the table is a pure function of the code point (0-127).
//
// Each of the 128 ASCII code points is described by its decimal / hex / octal /
// binary forms, a display glyph, a human name, whether it is printable, whether
// it is a control character, and (for control chars that have one) a C-style
// escape sequence.

export interface Entry {
  /** Decimal code point, 0-127. */
  dec: number;
  /** Uppercase hex, e.g. "0x41". */
  hex: string;
  /** Zero-padded 3-digit octal, e.g. "101". */
  oct: string;
  /** Zero-padded 8-bit binary, e.g. "01000001". */
  binary: string;
  /** Display glyph: the literal char for printables, a control-picture glyph for controls. */
  char: string;
  /** Human-readable name, e.g. "Line Feed (LF)", "Uppercase A", "Space". */
  name: string;
  /** True for 32-126 (visible or space). */
  printable: boolean;
  /** True for 0-31 and 127. */
  control: boolean;
  /** C-style escape for control chars that have one (e.g. "\\n"), else undefined. */
  escape?: string;
}

// Official ASCII control-character names (0-31 and 127).
const CONTROL_NAMES: Record<number, string> = {
  0: 'Null (NUL)',
  1: 'Start of Heading (SOH)',
  2: 'Start of Text (STX)',
  3: 'End of Text (ETX)',
  4: 'End of Transmission (EOT)',
  5: 'Enquiry (ENQ)',
  6: 'Acknowledge (ACK)',
  7: 'Bell (BEL)',
  8: 'Backspace (BS)',
  9: 'Horizontal Tab (HT)',
  10: 'Line Feed (LF)',
  11: 'Vertical Tab (VT)',
  12: 'Form Feed (FF)',
  13: 'Carriage Return (CR)',
  14: 'Shift Out (SO)',
  15: 'Shift In (SI)',
  16: 'Data Link Escape (DLE)',
  17: 'Device Control 1 (DC1)',
  18: 'Device Control 2 (DC2)',
  19: 'Device Control 3 (DC3)',
  20: 'Device Control 4 (DC4)',
  21: 'Negative Acknowledge (NAK)',
  22: 'Synchronous Idle (SYN)',
  23: 'End of Transmission Block (ETB)',
  24: 'Cancel (CAN)',
  25: 'End of Medium (EM)',
  26: 'Substitute (SUB)',
  27: 'Escape (ESC)',
  28: 'File Separator (FS)',
  29: 'Group Separator (GS)',
  30: 'Record Separator (RS)',
  31: 'Unit Separator (US)',
  127: 'Delete (DEL)',
};

// C-style escape sequences for the control chars that have a standard/common one.
const ESCAPES: Record<number, string> = {
  0: '\\0',
  7: '\\a',
  8: '\\b',
  9: '\\t',
  10: '\\n',
  11: '\\v',
  12: '\\f',
  13: '\\r',
  27: '\\e',
};

// Names for printable punctuation & symbols (letters and digits are derived).
const SYMBOL_NAMES: Record<number, string> = {
  32: 'Space',
  33: 'Exclamation mark',
  34: 'Quotation mark',
  35: 'Number sign',
  36: 'Dollar sign',
  37: 'Percent sign',
  38: 'Ampersand',
  39: 'Apostrophe',
  40: 'Left parenthesis',
  41: 'Right parenthesis',
  42: 'Asterisk',
  43: 'Plus sign',
  44: 'Comma',
  45: 'Hyphen / Minus',
  46: 'Full stop',
  47: 'Slash',
  58: 'Colon',
  59: 'Semicolon',
  60: 'Less-than sign',
  61: 'Equals sign',
  62: 'Greater-than sign',
  63: 'Question mark',
  64: 'At sign',
  91: 'Left bracket',
  92: 'Backslash',
  93: 'Right bracket',
  94: 'Circumflex / Caret',
  95: 'Underscore',
  96: 'Grave accent',
  123: 'Left brace',
  124: 'Vertical bar',
  125: 'Right brace',
  126: 'Tilde',
};

/** Derive a name for a printable letter or digit. */
function letterName(code: number): string {
  if (code >= 48 && code <= 57) return `Digit ${code - 48}`;
  if (code >= 65 && code <= 90) return `Uppercase ${String.fromCharCode(code)}`;
  if (code >= 97 && code <= 122) return `Lowercase ${String.fromCharCode(code)}`;
  return String.fromCharCode(code);
}

/** Build a single entry from its code point. */
function makeEntry(code: number): Entry {
  const control = code <= 31 || code === 127;
  const printable = !control;
  const hex = '0x' + code.toString(16).toUpperCase().padStart(2, '0');
  const oct = code.toString(8).padStart(3, '0');
  const binary = code.toString(2).padStart(8, '0');
  // Control-picture glyph: U+2400 for 0-31, U+2421 for DEL.
  const char = control ? (code === 127 ? '␡' : String.fromCharCode(0x2400 + code)) : String.fromCharCode(code);
  const name = control ? CONTROL_NAMES[code] : (SYMBOL_NAMES[code] ?? letterName(code));
  const escape = control && code in ESCAPES ? ESCAPES[code] : undefined;
  return { dec: code, hex, oct, binary, char, name, printable, control, escape };
}

/** The full 128-entry ASCII table, indexed by code point. */
export const ENTRY: Entry[] = Array.from({ length: 128 }, (_, i) => makeEntry(i));

/** Look up a single entry by code point. Returns null for out-of-range / non-integer input. */
export function getEntry(code: number): Entry | null {
  if (!Number.isInteger(code) || code < 0 || code > 127) return null;
  return ENTRY[code];
}

/**
 * Filter the table. `query` is a case-insensitive substring matched against
 * dec / hex / oct / binary / name / char / escape. `printableOnly` hides
 * controls. `min` / `max` clamp the decimal range (defaults 0-127).
 */
export function filterTable(opts: {
  query?: string;
  printableOnly?: boolean;
  min?: number;
  max?: number;
}): Entry[] {
  const q = (opts.query ?? '').trim().toLowerCase();
  const lo = opts.min ?? 0;
  const hi = opts.max ?? 127;
  return ENTRY.filter((e) => {
    if (opts.printableOnly && !e.printable) return false;
    if (e.dec < lo || e.dec > hi) return false;
    if (q === '') return true;
    const hay = [
      String(e.dec),
      e.hex.toLowerCase(),
      e.oct,
      e.binary,
      e.name.toLowerCase(),
      e.char.toLowerCase(),
      e.escape ?? '',
    ];
    return hay.some((h) => h.includes(q));
  });
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →