CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tanstack--table-core

Headless UI for building powerful tables & datagrids for TS/JS

Pending
Overview
Eval results
Files

column-system.mddocs/

Column System

Comprehensive column definition and management system supporting accessor functions, display columns, grouped columns, and various column types with full TypeScript type safety.

Capabilities

Column Helper

Utility for creating strongly-typed column definitions with proper type inference and accessor patterns.

/**
 * Creates a typed column helper for building column definitions
 * @returns ColumnHelper instance with type-safe methods
 */
function createColumnHelper<TData extends RowData>(): ColumnHelper<TData>;

interface ColumnHelper<TData extends RowData> {
  /** Create accessor column with automatic type inference */
  accessor<TAccessor extends AccessorFn<TData> | DeepKeys<TData>>(
    accessor: TAccessor,
    column: ColumnDefBase<TData, any>
  ): ColumnDef<TData, any>;
  /** Create display-only column with no data access */
  display(column: DisplayColumnDef<TData>): DisplayColumnDef<TData, unknown>;
  /** Create grouped column with sub-columns */
  group(column: GroupColumnDef<TData>): GroupColumnDef<TData, unknown>;
}

Usage Examples:

import { createColumnHelper } from "@tanstack/table-core";

type Person = {
  firstName: string;
  lastName: string;
  age: number;
  address: {
    street: string;
    city: string;
  };
};

const columnHelper = createColumnHelper<Person>();

// Accessor column with key
const firstNameColumn = columnHelper.accessor('firstName', {
  header: 'First Name',
  cell: info => info.getValue(),
});

// Accessor column with function
const fullNameColumn = columnHelper.accessor(
  row => `${row.firstName} ${row.lastName}`,
  {
    id: 'fullName',
    header: 'Full Name',
    cell: info => info.getValue(),
  }
);

// Deep accessor for nested properties
const cityColumn = columnHelper.accessor('address.city', {
  header: 'City',
  cell: info => info.getValue(),
});

// Display column
const actionsColumn = columnHelper.display({
  id: 'actions',
  header: 'Actions',
  cell: props => (
    <button onClick={() => console.log(props.row.original)}>
      Edit
    </button>
  ),
});

// Group column
const nameGroup = columnHelper.group({
  header: 'Name',
  columns: [firstNameColumn, lastNameColumn],
});

Column Definitions

Core column definition types supporting different column patterns and behaviors.

/** Union type of all possible column definitions */
type ColumnDef<TData extends RowData, TValue = unknown> = 
  | AccessorKeyColumnDef<TData, TValue>
  | AccessorFnColumnDef<TData, TValue>
  | DisplayColumnDef<TData, TValue>
  | GroupColumnDef<TData, TValue>;

/** Base column definition with common properties */
interface ColumnDefBase<TData extends RowData, TValue = unknown> {
  /** Unique identifier for the column */
  id?: string;
  /** Header content for the column */
  header?: ColumnDefTemplate<HeaderContext<TData, TValue>>;
  /** Footer content for the column */
  footer?: ColumnDefTemplate<HeaderContext<TData, TValue>>;
  /** Cell content renderer */
  cell?: ColumnDefTemplate<CellContext<TData, TValue>>;
  /** Custom meta information for the column */
  meta?: ColumnMeta<TData, TValue>;
  /** Enable/disable this specific column */
  enableHiding?: boolean;
}

/** Column definition using property key accessor */
interface AccessorKeyColumnDef<TData extends RowData, TValue = unknown> 
  extends ColumnDefBase<TData, TValue> {
  /** Property key to access from row data */
  accessorKey: DeepKeys<TData>;
  /** Optional accessor function override */
  accessorFn?: AccessorFn<TData, TValue>;
}

/** Column definition using function accessor */
interface AccessorFnColumnDef<TData extends RowData, TValue = unknown> 
  extends ColumnDefBase<TData, TValue> {
  /** Function to extract value from row data */
  accessorFn: AccessorFn<TData, TValue>;
  id: string;
}

/** Display column with no data access */
interface DisplayColumnDef<TData extends RowData, TValue = unknown> 
  extends ColumnDefBase<TData, TValue> {
  id: string;
}

/** Group column containing sub-columns */
interface GroupColumnDef<TData extends RowData, TValue = unknown> 
  extends ColumnDefBase<TData, TValue> {
  /** Array of sub-columns */
  columns: ColumnDef<TData, any>[];
  id?: string;
}

Column Core Interface

The core column interface providing access to column properties and methods.

interface Column<TData extends RowData, TValue = unknown> extends 
  CoreColumn<TData, TValue>,
  VisibilityColumn,
  ColumnOrderColumn,
  ColumnPinningColumn,
  FacetedColumn<TData>,
  ColumnFiltersColumn<TData>,
  GlobalFilterColumn,
  SortingColumn<TData>,
  GroupingColumn<TData>,
  ColumnSizingColumn {}

interface CoreColumn<TData extends RowData, TValue = unknown> {
  /** Unique column identifier */
  id: string;
  /** Depth of the column in nested structure */
  depth: number;
  /** Original column definition */
  columnDef: ColumnDef<TData, TValue>;
  /** Sub-columns if this is a group column */
  columns: Column<TData, TValue>[];
  /** Parent column if this is a sub-column */
  parent?: Column<TData, TValue>;
  /** Accessor function for extracting values */
  accessorFn?: AccessorFn<TData, TValue>;
  /** Get flattened array of all sub-columns */
  getFlatColumns(): Column<TData, TValue>[];
  /** Get array of leaf columns (no sub-columns) */
  getLeafColumns(): Column<TData, TValue>[];
}

Usage Examples:

// Access column properties
const column = table.getColumn('firstName');
console.log(column.id); // 'firstName'
console.log(column.depth); // 0

// Get nested columns
const groupColumn = table.getColumn('nameGroup');
const leafColumns = groupColumn.getLeafColumns();

// Check if column has sub-columns
const hasSubColumns = column.columns.length > 0;

Accessor Functions

Functions for extracting values from row data with strong typing support.

/** Function type for accessing row data values */
type AccessorFn<TData extends RowData, TValue = unknown> = (
  originalRow: TData,
  index: number
) => TValue;

/** Utility type for deep property key access */
type DeepKeys<T> = T extends Record<string, any>
  ? {
      [K in keyof T]-?: K extends string | number
        ? T[K] extends Record<string, any>
          ? `${K}` | `${K}.${DeepKeys<T[K]>}`
          : `${K}`
        : never;
    }[keyof T]
  : never;

/** Utility type for extracting deep property values */
type DeepValue<T, TProp extends DeepKeys<T>> = T extends Record<string, any>
  ? TProp extends `${infer TKey}.${infer TRest}`
    ? TKey extends keyof T
      ? TRest extends DeepKeys<T[TKey]>
        ? DeepValue<T[TKey], TRest>
        : never
      : never
    : TProp extends keyof T
    ? T[TProp]
    : never
  : never;

Usage Examples:

type User = {
  profile: {
    personal: {
      name: string;
      age: number;
    };
    contact: {
      email: string;
    };
  };
};

// Deep key examples
type NameKey = 'profile.personal.name'; // Valid
type EmailKey = 'profile.contact.email'; // Valid

// Accessor function examples
const nameAccessor: AccessorFn<User, string> = (row, index) => 
  row.profile.personal.name;

const ageAccessor: AccessorFn<User, number> = (row, index) => 
  row.profile.personal.age;

// Using with column helper
const nameColumn = columnHelper.accessor('profile.personal.name', {
  header: 'Name',
  cell: info => info.getValue(), // Type: string
});

Column Templates

Flexible templating system for column headers, cells, and footers.

/** Template type that can be a value or function */
type ColumnDefTemplate<TProps> = 
  | string 
  | ((props: TProps) => any);

/** Template rendering function */
type StringOrTemplateHeader<TData extends RowData, TValue = unknown> = 
  | string 
  | ((props: HeaderContext<TData, TValue>) => any);

Usage Examples:

// String template
const simpleColumn = columnHelper.accessor('name', {
  header: 'Name',
  cell: 'Default Cell Content',
});

// Function template
const complexColumn = columnHelper.accessor('status', {
  header: ({ column }) => (
    <button onClick={() => column.toggleSorting()}>
      Status {column.getIsSorted() === 'asc' ? '↑' : column.getIsSorted() === 'desc' ? '↓' : ''}
    </button>
  ),
  cell: ({ getValue, row }) => {
    const status = getValue();
    return (
      <span className={`status-${status}`}>
        {status} ({row.original.id})
      </span>
    );
  },
});

Column Metadata

Custom metadata system for attaching additional information to columns.

/** Custom metadata interface for columns */
interface ColumnMeta<TData extends RowData, TValue = unknown> {
  /** Any custom properties */
  [key: string]: any;
}

Usage Examples:

const columnWithMeta = columnHelper.accessor('price', {
  header: 'Price',
  meta: {
    type: 'currency',
    format: 'USD',
    validation: {
      required: true,
      min: 0,
    },
    className: 'text-right font-mono',
  },
  cell: ({ getValue, column }) => {
    const value = getValue();
    const meta = column.columnDef.meta;
    
    if (meta?.type === 'currency') {
      return new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: meta.format || 'USD',
      }).format(value);
    }
    
    return value;
  },
});

// Access meta in rendering
const meta = column.columnDef.meta;

Column Resolution

Internal column definition resolution and processing.

/** Resolved column definition after processing */
interface ColumnDefResolved<TData extends RowData, TValue = unknown> 
  extends ColumnDefBase<TData, TValue> {
  /** Resolved accessor function */
  accessorFn?: AccessorFn<TData, TValue>;
  /** Resolved column ID */
  id: string;
}

/** Creates a resolved column from definition */
function createColumn<TData extends RowData, TValue = unknown>(
  table: Table<TData>,
  columnDef: ColumnDef<TData, TValue>,
  depth: number,
  parent?: Column<TData, any>
): Column<TData, TValue>;

This system automatically resolves column definitions, generates IDs when missing, and creates the appropriate accessor functions based on the column type.

Install with Tessl CLI

npx tessl i tessl/npm-tanstack--table-core

docs

builtin-functions.md

column-features.md

column-system.md

index.md

row-features.md

row-models.md

sorting-filtering.md

table-management.md

tile.json