TypeScript Simple Type Checker

1.0.7 · maintenance · verified Sun Apr 19

ts-simple-type is a TypeScript utility library (current stable version 1.0.7, last published July 2020) designed to provide essential helper functions for analyzing and comparing TypeScript types. It aims to bridge gaps in the native TypeScript compiler API, particularly for direct assignability checks and programmatically constructing types, as noted by discussions in TypeScript GitHub issues #9879 and #29432. The library works by converting native TypeScript `ts.Type` objects into its own `SimpleType` interface, which offers a more standardized and easily serializable representation. This `SimpleType` abstraction facilitates advanced type analysis, comparison, and even serialization for use in various environments, including browsers. A key differentiator is its extensive test suite, comprising over 35,000 tests that validate its type-checking results against actual TypeScript diagnostics. Despite its usefulness, the package shows a slower release cadence, with the last update in 2020, suggesting it is now in a maintenance state rather than active development.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to set up a basic TypeScript program to obtain a `ts.TypeChecker`, extract types from code, and then use `ts-simple-type`'s `isAssignableToType` function to check type compatibility. It also shows conversion to `SimpleType` and direct usage of `SimpleType` objects. Requires `typescript` package to be installed as a peer dependency.

import ts from 'typescript';
import { isAssignableToType, toSimpleType, typeToString, SimpleType } from 'ts-simple-type';

// 1. Set up a minimal TypeScript program to get a TypeChecker
const code = `
  type MyNumber = number;
  let a: MyNumber = 10;
  let b: string = "hello";
  let d: string | number = 5;
`;

const fileName = 'test-file.ts';
const sourceFile = ts.createSourceFile(fileName, code, ts.ScriptTarget.ES2015, true);

const host: ts.LanguageServiceHost = {
  getScriptFileNames: () => [fileName],
  getScriptVersion: (f) => '1',
  getScriptSnapshot: (f) => {
    if (f === fileName) {
      return ts.ScriptSnapshot.fromString(code);
    }
    return undefined;
  },
  getCurrentDirectory: () => '/',
  getCompilationSettings: () => ({}),
  getDefaultLibFileName: ts.getDefaultLibFileName,
  fileExists: (f) => f === fileName,
  readFile: (f) => (f === fileName ? code : undefined),
  readDirectory: () => [],
};

const program = ts.createProgram([fileName], {}, host);
const typeChecker = program.getTypeChecker();

// 2. Extract TypeScript types from the AST
const typeAliases = sourceFile.statements.filter(ts.isTypeAliasDeclaration);
const varStatements = sourceFile.statements.filter(ts.isVariableStatement);

const myNumberType = typeChecker.getTypeFromTypeNode(typeAliases[0].type); // Type of 'MyNumber'

const aSymbol = typeChecker.getSymbolAtLocation(varStatements[0].declarationList.declarations[0].name);
const aType = aSymbol ? typeChecker.getTypeOfSymbolAtLocation(aSymbol, aSymbol.valueDeclaration!) : undefined; // Type of 'a'

const bSymbol = typeChecker.getSymbolAtLocation(varStatements[1].declarationList.declarations[0].name);
const bType = bSymbol ? typeChecker.getTypeOfSymbolAtLocation(bSymbol, bSymbol.valueDeclaration!) : undefined; // Type of 'b'

const dSymbol = typeChecker.getSymbolAtLocation(varStatements[2].declarationList.declarations[0].name);
const dType = dSymbol ? typeChecker.getTypeOfSymbolAtLocation(dSymbol, dSymbol.valueDeclaration!) : undefined; // Type of 'd'

if (aType && bType && dType) {
  // 3. Use ts-simple-type to check assignability and convert types
  console.log(`Is '${typeToString(toSimpleType(aType, typeChecker))}' assignable to 'number'? ${isAssignableToType(aType, myNumberType, typeChecker)}`); // true
  console.log(`Is '${typeToString(toSimpleType(bType, typeChecker))}' assignable to 'number'? ${isAssignableToType(bType, myNumberType, typeChecker)}`); // false
  console.log(`Is '${typeToString(toSimpleType(dType, typeChecker))}' assignable to 'number'? ${isAssignableToType(dType, myNumberType, typeChecker)}`); // true

  // Demonstrate working with SimpleType directly
  const customStringType: SimpleType = { kind: "STRING" };
  const customNumberType: SimpleType = { kind: "NUMBER" };
  console.log(`Is '${typeToString(toSimpleType(bType, typeChecker))}' assignable to custom STRING type? ${isAssignableToType(bType, customStringType, typeChecker)}`); // true
  console.log(`Is '${typeToString(toSimpleType(aType, typeChecker))}' assignable to custom NUMBER type? ${isAssignableToType(aType, customNumberType, typeChecker)}`); // true
}

view raw JSON →