Public

https://micro-cms-blog-seven.vercel.app/article/st6w8-890

Public note: https://narrow-jelly-0b4.notion.site/Public-Notes-c6be3f6df2a84b8cb32f9cab2fc56440?pvs=4

https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming

Present link: https://docs.google.com/presentation/d/1HZb9TpEj4FgwENkjC6v_Dit4uarCdfe5VW8O3pSIBxQ/edit?usp=sharing

Repo: https://github.com/hoangthau/type-helpers

Type challenge

import { Equal, Expect } from "../helpers/type-utils";
import { S } from "ts-toolbelt";

type UserPath = "/users/:id";

type UserOrganisationPath = "/users/:id/organisations/:organisationId";

type Keys<T extends string>= S.Split<T, '/'>[number];

type ExtractPathParams<T extends string> = {
  [K in Keys<T> as K extends `:${infer P}` ? P : never]: string
};

type Check = ExtractPathParams<UserPath>;
type Check2 = ExtractPathParams<UserOrganisationPath>;

type tests = [
  Expect<Equal<ExtractPathParams<UserPath>, { id: string }>>,
  Expect<
    Equal<
      ExtractPathParams<UserOrganisationPath>,
      { id: string; organisationId: string }
    >
  >,
];

// Next
interface Attributes {
  firstName: string;
  lastName: string;
  age: number;
}

type AttributeGetters = {
  [K in keyof Attributes as `get${Capitalize<K>}`]: () => Attributes[K];
};

Vue Docs

https://hoangthau.notion.site/hoangthau/KT-357b7a5cd88d44548e50565068dd17c9