Type utilities for working with TypeScript + ESLint together
—
Functions for analyzing type names, structure, and relationships. These utilities help extract meaningful information from TypeScript types and understand type composition.
Functions for extracting human-readable names from TypeScript types.
/**
* Get the type name of a given type. Handles string-like types, type parameters,
* unions, and intersections specially.
*/
function getTypeName(typeChecker: ts.TypeChecker, type: ts.Type): string;Usage Examples:
import { getTypeName } from "@typescript-eslint/type-utils";
// In an ESLint rule
export default {
create(context) {
const services = context.parserServices;
const checker = services.program.getTypeChecker();
return {
VariableDeclaration(node) {
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
const type = checker.getTypeAtLocation(tsNode);
const typeName = getTypeName(checker, type);
console.log(`Variable type: ${typeName}`);
// Example outputs:
// "string" for string type
// "number | string" for union types
// "{ name: string; age: number }" for object types
}
};
}
};Functions for analyzing what types contain and their structure.
/**
* Checks whether a type contains all specified type names
* @param type - Type being checked by name
* @param allowAny - Whether to consider `any` and `unknown` to match
* @param allowedNames - Symbol names checking on the type
* @param matchAnyInstead - Whether to check if any parts match rather than all parts
* @returns Whether the type is, extends, or contains the allowed names
*/
function containsAllTypesByName(
type: ts.Type,
allowAny: boolean,
allowedNames: Set<string>,
matchAnyInstead?: boolean
): boolean;Usage Examples:
import { containsAllTypesByName } from "@typescript-eslint/type-utils";
// Check if a type contains specific type names
const allowedTypes = new Set(['string', 'number']);
const containsAllowed = containsAllTypesByName(
type,
false, // don't allow any/unknown
allowedTypes,
false // all parts must match
);
if (containsAllowed) {
// Type only contains string and number types
}
// Check if any part matches (useful for unions)
const hasAnyAllowed = containsAllTypesByName(
type,
false,
allowedTypes,
true // match any instead of all
);Functions for working with TypeScript's internal type flags system.
/**
* Gets all of the type flags in a type, iterating through unions automatically
*/
function getTypeFlags(type: ts.Type): ts.TypeFlags;
/**
* Checks if specific type flags are set. Decomposes union types and checks all constituents.
* If type is union, checks flags of every union constituent.
*/
function isTypeFlagSet(type: ts.Type, flagsToCheck: ts.TypeFlags): boolean;Usage Examples:
import { getTypeFlags, isTypeFlagSet } from "@typescript-eslint/type-utils";
import * as ts from "typescript";
// Get all flags for a type
const flags = getTypeFlags(someType);
console.log(`Type flags: ${flags}`);
// Check for specific flags
if (isTypeFlagSet(someType, ts.TypeFlags.String)) {
// Type has string flag
}
if (isTypeFlagSet(someType, ts.TypeFlags.Union)) {
// Type is a union type
}
// Common flag checks
if (isTypeFlagSet(someType, ts.TypeFlags.Any)) {
context.report({ node, messageId: "noAnyType" });
}
if (isTypeFlagSet(someType, ts.TypeFlags.Undefined | ts.TypeFlags.Null)) {
// Type includes undefined or null
}Additional utilities for text processing and type analysis.
/**
* Indicates whether identifiers require the use of quotation marks when accessing
* property definitions and dot notation
*/
function requiresQuoting(name: string, target?: ts.ScriptTarget): boolean;Usage Examples:
import { requiresQuoting } from "@typescript-eslint/type-utils";
import * as ts from "typescript";
// Check if property names need quoting
const needsQuotes = requiresQuoting("my-property"); // true
const noQuotes = requiresQuoting("myProperty"); // false
const withTarget = requiresQuoting("let", ts.ScriptTarget.ES5); // true (reserved word)
// Use in property access suggestions
if (needsQuotes) {
suggestion = `obj["${propertyName}"]`;
} else {
suggestion = `obj.${propertyName}`;
}// Example: Analyzing complex union types
import { getTypeName, containsAllTypesByName, isTypeFlagSet } from "@typescript-eslint/type-utils";
function analyzeUnionType(type: ts.Type, checker: ts.TypeChecker) {
const typeName = getTypeName(checker, type);
if (isTypeFlagSet(type, ts.TypeFlags.Union)) {
// It's a union type
const allowedPrimitives = new Set(['string', 'number', 'boolean']);
if (containsAllTypesByName(type, false, allowedPrimitives, true)) {
console.log(`Union contains primitives: ${typeName}`);
}
}
}// Example: Categorizing types by flags
import { getTypeFlags } from "@typescript-eslint/type-utils";
import * as ts from "typescript";
function categorizeType(type: ts.Type): string {
const flags = getTypeFlags(type);
if (flags & ts.TypeFlags.String) return "string";
if (flags & ts.TypeFlags.Number) return "number";
if (flags & ts.TypeFlags.Boolean) return "boolean";
if (flags & ts.TypeFlags.Undefined) return "undefined";
if (flags & ts.TypeFlags.Null) return "null";
if (flags & ts.TypeFlags.Any) return "any";
if (flags & ts.TypeFlags.Unknown) return "unknown";
if (flags & ts.TypeFlags.Never) return "never";
if (flags & ts.TypeFlags.Union) return "union";
if (flags & ts.TypeFlags.Intersection) return "intersection";
return "complex";
}Install with Tessl CLI
npx tessl i tessl/npm-typescript-eslint--type-utils