Skip to content

Instantly share code, notes, and snippets.

@AykutSarac
Last active December 29, 2023 11:50
Show Gist options
  • Save AykutSarac/cc422ccbb391d74e6fec02e4bdc6165d to your computer and use it in GitHub Desktop.
Save AykutSarac/cc422ccbb391d74e6fec02e4bdc6165d to your computer and use it in GitHub Desktop.
Zero dependency CSV parser in TypeScript with generics support
type CSVRow<T> = Record<keyof T, string | number>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
class CSVParser<T = any> {
private rows: CSVRow<T>[];
private header: (keyof T)[];
constructor(csvData: string) {
this.rows = this.parseCSV(csvData);
this.header = this.rows.length > 0 ? (Object.keys(this.rows[0]) as (keyof T)[]) : [];
}
private parseCSV(csvData: string): CSVRow<T>[] {
const [header, ...rows] = csvData
.split("\n")
.map(row => row.split(",").map(cell => cell.trim()));
return rows.map(row =>
row.reduce((acc, cell, index) => {
const columnName = header[index].trim() as keyof T;
acc[columnName] = isNaN(Number(cell)) ? cell : Number(cell);
return acc;
}, {} as CSVRow<T>)
);
}
private getColumnIndex(columnName: keyof T): number {
return this.header.indexOf(columnName);
}
getValues<K extends keyof T>(columnName: K): T[K][] {
const columnIndex = this.getColumnIndex(columnName);
if (columnIndex === -1) {
throw new Error(`Column ${String(columnName)} not found`);
}
return this.rows.map(row => row[columnName] as T[K]);
}
getRow(index: number): CSVRow<T> | undefined {
return this.rows[index];
}
getColumnValues<K extends keyof T>(columnName: K): T[K][] {
const columnIndex = this.getColumnIndex(columnName);
if (columnIndex === -1) {
throw new Error(`Column ${String(columnName)} not found`);
}
return this.rows.map(row => row[columnName] as T[K]);
}
getAllData(): CSVRow<T>[] {
return this.rows;
}
}
@AykutSarac
Copy link
Author

Example usage:

// Example usage:
interface Person {
  Name: string;
  Age: number;
  City: string;
}

const csvData = `Name, Age, City
John Doe, 30, New York
Jane Smith, 25, San Francisco
Bob Johnson, 35, Los Angeles
Alice Williams, 28, Chicago`;

try {
  const csv = new CSVParser<Person>(csvData);

  console.log(csv.getValues("Age")); // Output: [30, 25, 35, 28]
  console.log(csv.getRow(1)); // Output: { Name: 'Jane Smith', Age: 25, City: 'San Francisco' }
  console.log(csv.getColumnValues("City")); // Output: ['New York', 'San Francisco', 'Los Angeles', 'Chicago']
  console.log(csv.getAllData()); // Output: Array of all rows as objects
} catch (error) {
  console.error(error.message);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment