We use cookies to enhance your experience on the site
CodeWorlds

Main Project: Typed Cosmic Dashboard

Time to combine all the knowledge from this module into one project! You'll build a typed cosmic dashboard that uses:

  • Interfaces and types - for planet, mission, and crew data
  • Typed components - with full props typing
  • useState with generics - for state management
  • Typed events - in forms and interactions
  • Discriminated unions - for different data types
  • Context API with TypeScript - for global state

Project Description

The cosmic dashboard consists of several sections:

  1. Main panel - displays mission statistics
  2. Cosmic objects list - with filtering by type (planets, stars, asteroids)
  3. Add form - with full event typing
  4. Theme switcher - dark/light with Context API

Type Architecture

1// Base interface
2interface SpaceEntity {
3  id: string;
4  name: string;
5  discoveredYear: number;
6}
7
8// Discriminated union - different object types
9interface PlanetEntity extends SpaceEntity {
10  kind: "planet";
11  radius: number;
12  habitable: boolean;
13}
14
15interface StarEntity extends SpaceEntity {
16  kind: "star";
17  temperature: number;
18  spectralClass: "O" | "B" | "A" | "F" | "G" | "K" | "M";
19}
20
21interface AsteroidEntity extends SpaceEntity {
22  kind: "asteroid";
23  diameter: number;
24  composition: string;
25}
26
27type CosmicObject = PlanetEntity | StarEntity | AsteroidEntity;
28
29// Dashboard state
30interface DashboardState {
31  objects: CosmicObject[];
32  filter: CosmicObject["kind"] | "all";
33  searchQuery: string;
34}

Generic DataTable Component

1// Generic table component with full typing
2interface Column<T> {
3  key: keyof T;
4  label: string;
5  render?: (value: T[keyof T], item: T) => React.ReactNode;
6}
7
8interface DataTableProps<T extends { id: string }> {
9  data: T[];
10  columns: Column<T>[];
11  onRowClick?: (item: T) => void;
12}
13
14function DataTable<T extends { id: string }>({
15  data, columns, onRowClick
16}: DataTableProps<T>) {
17  return (
18    <table>
19      <thead>
20        <tr>
21          {columns.map(col => (
22            <th key={String(col.key)}>{col.label}</th>
23          ))}
24        </tr>
25      </thead>
26      <tbody>
27        {data.map(item => (
28          <tr key={item.id} onClick={() => onRowClick?.(item)}>
29            {columns.map(col => (
30              <td key={String(col.key)}>
31                {col.render
32                  ? col.render(item[col.key], item)
33                  : String(item[col.key])}
34              </td>
35            ))}
36          </tr>
37        ))}
38      </tbody>
39    </table>
40  );
41}

Typed Add Form

1type NewObjectForm =
2  | { kind: "planet"; name: string; radius: string; habitable: boolean }
3  | { kind: "star"; name: string; temperature: string; spectralClass: string }
4  | { kind: "asteroid"; name: string; diameter: string; composition: string };
5
6function AddObjectForm({ onAdd }: { onAdd: (obj: CosmicObject) => void }) {
7  const [kind, setKind] = useState<CosmicObject["kind"]>("planet");
8  const [name, setName] = useState("");
9
10  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
11    e.preventDefault();
12    // Creates the appropriate object based on the selected type
13    const id = crypto.randomUUID();
14    const year = new Date().getFullYear();
15
16    // ... object creation logic
17  };
18
19  return (
20    <form onSubmit={handleSubmit}>
21      <select
22        value={kind}
23        onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
24          setKind(e.target.value as CosmicObject["kind"])
25        }
26      >
27        <option value="planet">Planet</option>
28        <option value="star">Star</option>
29        <option value="asteroid">Asteroid</option>
30      </select>
31      <input value={name} onChange={e => setName(e.target.value)} />
32      <button type="submit">Add</button>
33    </form>
34  );
35}

Complete Project

Below you'll find the complete implementation of the cosmic dashboard with full TypeScript typing. Analyze the code, modify it, and experiment with types!

Go to CodeWorlds