Skip to content

Instantly share code, notes, and snippets.

@pongo
Created February 17, 2021 13:23
Show Gist options
  • Save pongo/480936c95fb4e959484c04ae68119e6d to your computer and use it in GitHub Desktop.
Save pongo/480936c95fb4e959484c04ae68119e6d to your computer and use it in GitHub Desktop.
typesafe table render on typescript

Показал тут на днях гоферам и пхпшникам кусок кода, который рендерит табличку. Их языки не позволяют творить такие штуки со статической типизацией. Матерились и говорили, что мы (кто пишет на тс) ебанутые, что это сложно, что «эта ваша математика на типах от того, что вы нихера не понимаете в программировании». Когда объяснил, как работает, сказали «а, ну да, красиво».


это вообще офигенная штука — в react-table и rc-table (из and.design) так же сделано — можно указать только accessor'ры для существующих полей в строке таблицы. на бэке поменялась DTO-шка, на фронте упало с ошибкой компиляции.


посмотрел код . я 5лет писал на C#. сейчас год работаю typescript+angular. по моему мнению typescript позволяет делать легко фантастические вещи с типами . просто какая то магия . конечно можно и с помощью C# подобные штуки вертеть . но кода-затраты будут гораздо выше .

type Renderable = string | number;
type Values<O extends object> = O[keyof O];
type ColumnMap<T> = {
[K in keyof T]: {
label: string;
name: K;
renderer: (value: T[K]) => Renderable;
};
};
type Column<T> = Values<ColumnMap<T>>;
type Columns<T> = Column<T>[];
declare function render<T>(data: T[], columns: Columns<T>): void
// пользовательский код
const users = [
{ id: 1, name: "petya", age: new Date(1995, 11, 17) },
{ id: 2, name: "vasya", age: new Date(1992, 5, 14) }
];
// валидный код
render(users, [
{ label: "ID", name: "id", renderer: (id) => id.toFixed(1) },
{ label: "Name", name: "name", renderer: (name) => name.toUpperCase() },
{ label: "Year", name: "age", renderer: (age) => age.getFullYear() },
{ label: "Month", name: "age", renderer: (age) => age.getMonth() }
]);
// невалидный код
render(users, [
{ label: "ID", name: "invalid", renderer: (id) => id.toFixed(1) },
{ label: "ID", name: "age", renderer: (id) => id.toFixed(1) }
]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment