CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-yaml

JavaScript parser and stringifier for YAML documents with complete YAML 1.1 and 1.2 support

Overview
Eval results
Files

type-guards.mddocs/

Type Guards

Runtime type checking functions for identifying different node types in the YAML AST. These functions provide type safety when working with nodes and enable proper handling of different node types in traversal and manipulation operations.

Capabilities

Node Type Identification

Type guard functions that narrow TypeScript types and enable safe node manipulation.

/**
 * Check if value is a Document
 * @param node - Value to check
 * @returns Type predicate for Document
 */
function isDocument(node: unknown): node is Document;

/**
 * Check if value is any Node type
 * @param value - Value to check
 * @returns Type predicate for Node
 */
function isNode(value: unknown): value is Node;

/**
 * Check if node is a Scalar
 * @param node - Node to check
 * @returns Type predicate for Scalar
 */
function isScalar(node: unknown): node is Scalar;

/**
 * Check if node is a YAMLMap
 * @param node - Node to check
 * @returns Type predicate for YAMLMap
 */
function isMap(node: unknown): node is YAMLMap;

/**
 * Check if node is a YAMLSeq
 * @param node - Node to check
 * @returns Type predicate for YAMLSeq
 */
function isSeq(node: unknown): node is YAMLSeq;

/**
 * Check if node is a Pair
 * @param node - Node to check
 * @returns Type predicate for Pair
 */
function isPair(node: unknown): node is Pair;

/**
 * Check if node is an Alias
 * @param node - Node to check
 * @returns Type predicate for Alias
 */
function isAlias(node: unknown): node is Alias;

/**
 * Check if node is a Collection (YAMLMap or YAMLSeq)
 * @param node - Node to check
 * @returns Type predicate for Collection
 */
function isCollection(node: unknown): node is YAMLMap | YAMLSeq;

/**
 * Check if node has an anchor
 * @param node - Node to check
 * @returns True if node has anchor property
 */
function hasAnchor(node: Node): boolean;

Usage Examples:

import { 
  parseDocument, 
  isScalar, 
  isMap, 
  isSeq, 
  isAlias, 
  isCollection,
  isPair 
} from "yaml";

const doc = parseDocument(`
name: John Doe
age: 30
hobbies:
  - reading
  - coding
address:
  city: New York
  country: USA
alias_example: &shared_value "shared text"
alias_reference: *shared_value
`);

// Type-safe node processing
function processNode(node: unknown) {
  if (isScalar(node)) {
    console.log('Scalar value:', node.value);
    console.log('Scalar type:', node.type);
    
    // Safe to access scalar-specific properties
    if (typeof node.value === 'string') {
      console.log('String length:', node.value.length);
    }
  }
  
  else if (isMap(node)) {
    console.log('Map with', node.items.length, 'pairs');
    
    // Safe to iterate over map items
    node.items.forEach((pair, index) => {
      if (isPair(pair)) {
        console.log(`Pair ${index}:`, pair.key, '->', pair.value);
      }
    });
  }
  
  else if (isSeq(node)) {
    console.log('Sequence with', node.items.length, 'items');
    
    // Safe to iterate over sequence items
    node.items.forEach((item, index) => {
      console.log(`Item ${index}:`, item);
    });
  }
  
  else if (isAlias(node)) {
    console.log('Alias referencing:', node.source);
    
    // Safe to resolve alias
    const resolved = node.resolve(doc);
    console.log('Resolved value:', resolved);
  }
  
  // Generic collection handling
  if (isCollection(node)) {
    console.log('Collection type:', isMap(node) ? 'Map' : 'Sequence');
    console.log('Flow style:', node.flow);
    console.log('Item count:', node.items.length);
  }
}

// Process document contents
if (doc.contents) {
  processNode(doc.contents);
}

Advanced Type Checking

import { parseDocument, isDocument, isNode, hasAnchor } from "yaml";

// Document type checking
const doc = parseDocument('key: value');
if (isDocument(doc)) {
  // TypeScript knows this is a Document
  console.log('Document errors:', doc.errors.length);
  console.log('Document warnings:', doc.warnings.length);
}

// Node type checking with tree traversal
function traverseNodes(node: unknown) {
  if (!isNode(node)) {
    console.log('Not a node:', typeof node);
    return;
  }
  
  // TypeScript knows this is a Node type
  console.log('Node range:', node.range);
  console.log('Node comment:', node.comment);
  console.log('Has anchor:', hasAnchor(node));
  
  if (hasAnchor(node)) {
    console.log('Anchor name:', node.anchor);
  }
  
  // Recursively process collections
  if (isCollection(node)) {
    node.items.forEach(item => traverseNodes(item));
  }
}

// Safe document content access
if (doc.contents && isNode(doc.contents)) {
  traverseNodes(doc.contents);
}

Conditional Processing

import { parseDocument, isScalar, isMap, isSeq } from "yaml";

const doc = parseDocument(`
config:
  name: "MyApp"
  version: 1.0
  features:
    - auth
    - logging
  database:
    host: localhost
    port: 5432
`);

// Conditional processing based on node type
function extractStrings(node: unknown): string[] {
  const strings: string[] = [];
  
  if (isScalar(node)) {
    if (typeof node.value === 'string') {
      strings.push(node.value);
    }
  }
  
  else if (isMap(node)) {
    node.items.forEach(pair => {
      if (isPair(pair)) {
        strings.push(...extractStrings(pair.key));
        strings.push(...extractStrings(pair.value));
      }
    });
  }
  
  else if (isSeq(node)) {
    node.items.forEach(item => {
      strings.push(...extractStrings(item));
    });
  }
  
  return strings;
}

// Extract all strings from document
const allStrings = extractStrings(doc.contents);
console.log('All strings:', allStrings);

Working with Mixed Collections

import { 
  parseDocument, 
  isScalar, 
  isMap, 
  isSeq, 
  isPair,
  YAMLMap,
  YAMLSeq 
} from "yaml";

// Function to safely add items to collections
function addToCollection(collection: unknown, key: any, value: any) {
  if (isMap(collection)) {
    // Safe map operations
    collection.set(key, value);
    console.log('Added to map:', key, '->', value);
  }
  
  else if (isSeq(collection)) {
    // Safe sequence operations (ignore key for sequences)
    collection.add(value);
    console.log('Added to sequence:', value);
  }
  
  else {
    console.log('Not a collection, cannot add items');
  }
}

// Function to get collection size
function getCollectionSize(node: unknown): number {
  if (isCollection(node)) {
    return node.items.length;
  }
  return 0;
}

// Usage example
const doc = parseDocument('items: []');
const itemsNode = doc.get(['items'], true);

if (itemsNode) {
  console.log('Initial size:', getCollectionSize(itemsNode));
  addToCollection(itemsNode, null, 'first item');
  addToCollection(itemsNode, null, 'second item');
  console.log('Final size:', getCollectionSize(itemsNode));
}

Type Identity Symbols

The library uses internal symbols for type identification, which are also exported for advanced use cases.

/** Symbol used to identify Alias nodes */
declare const ALIAS: unique symbol;

/** Symbol used to identify Document nodes */
declare const DOC: unique symbol;

/** Symbol used to identify YAMLMap nodes */
declare const MAP: unique symbol;

/** Symbol used to identify Pair nodes */
declare const PAIR: unique symbol;

/** Symbol used to identify Scalar nodes */
declare const SCALAR: unique symbol;

/** Symbol used to identify YAMLSeq nodes */
declare const SEQ: unique symbol;

/** Symbol property used for node type identification */
declare const NODE_TYPE: unique symbol;

These symbols are used internally by the type guard functions but can also be accessed directly for advanced type checking scenarios.

Type Definitions

type Node = Alias | Scalar | YAMLMap | YAMLSeq;
type ParsedNode = Alias | Scalar<any> | YAMLMap<any, any> | YAMLSeq<any>;
type Collection = YAMLMap | YAMLSeq;

// Type guard function signatures
type TypeGuard<T> = (value: unknown) => value is T;

Install with Tessl CLI

npx tessl i tessl/npm-yaml

docs

ast-nodes.md

document-processing.md

error-handling.md

index.md

parse-stringify.md

parser-infrastructure.md

schema-configuration.md

tree-traversal.md

type-guards.md

utilities.md

tile.json