Upgrade to Pro — share decks privately, control downloads, hide ads and more …

T3 Stack and TypeScript ecosystem

T3 Stack and TypeScript ecosystem

Yosuke Kurami

January 18, 2023
Tweet

More Decks by Yosuke Kurami

Other Decks in Programming

Transcript

  1. About me - Twitter / GitHub: @Quramy - Web Developer

    (Node.js / Ruby on Rails ͷׂ߹͕ߴΊ) - Techfeed Expert (TypeScript)
  2. T3 Stack - 2022 ೥ ʹެ։͞Εͨ Web ΞϓϦέʔγϣϯ։ൃελοΫ - Backend

    / Frontend ૒ํΛ TypeScript Ͱهड़͢ΔલఏͷϥΠϒϥϦߏ ੒ - https://github.com/t3-oss/create-t3-app
  3. T3 Axiom: Typesafety is not optional The stated goal of

    Create T3 App is to provide the quickest way to start a new full-stack, typesafe web application. We take typesafety seriously in these parts as it improves our productivity and helps us ship fewer bugs. Any decision that compromises the typesafe nature of Create T3 App is a decision that should be made in a different project. https://create.t3.gg/en/introduction#typesafety-isnt-optional
  4. Typesafe ͱ͸ʁ - Question: ࣍ͷ TypeScript ίʔυ͸ TypesafeͰ͔͢ʁ - TypeScript

    Ͱ͋ͬͯ΋҆શͱ͸ݶΒͳ͍ - API Ϩεϙϯεͷܕ͕ any, fetch URL ΍ύϥϝʔλ෇༩ํ๏ - զʑʹͱͬͯͷ Typesafe : ΞϓϦέʔγϣϯʹޡΓ͕ࠞೖ͢ΔՄೳੑ͕੩తʹۃখԽ͞Ε͍ͯΔঢ়ଶ const product = await fetch(`/api/products/1234`).then(res => res.json())
  5. The unknown - TypeScript͕༧ଌͣ͠Β͍ྖҬ - JavaScriptҎ֎ͷΤίγεςϜͱͷ࿈ܞ - e.g. API req/res,

    database access, CSS / HTML template, etc... - ೗ԿʹunknownΛݮΒ͔͕͢DX޲্ͷ伴 https://speakerdeck.com/quramy/extends-developer-experience?slide=13 ΑΓ࠶ܝ
  6. tRPC - TypeScript ʹΑΔ Remote Procedure Call Λ࣮ݱ͢ΔϥΠϒϥϦ - ϑϧελοΫ

    TypeScript ։ൃʹಛԽ GraphQL ΍ Open API ͕ݴޠඇґଘͰ͋Δ఺ʹ͓͍ͯɺੑ࣭͕ҟͳΔ - Zod ΤίγεςϜͷҰͭ - T3 ( Next.js ) Ͱ࢖͏৔߹: react-query ΛϥϯλΠϜʹ༻͍Δ
  7. export const ProductDetail = () => { const { data,

    isFetching } = trpc.productDetail.useQuery({ id: "1234" }) if (isFetching || !data) return <div>Loading...</div> return ( <div> Product name: {data.name} </div> ) } Browser JS Node.js const getContext = () => ({ prisma }) const { router, procedure } = initTRPC.context<typeof getContext>().create() const productDetail = procedure .input(z.object({ id: z.string() })) .query(async ({ ctx: { prisma }, input: { id } }) => { const result = await prisma.product.findUnique({ where: { id } }) return { id: result.id, name: result.name, price: result.price, } }) export const appRouter = router({ productDetail, }) export type AppRouter = typeof appRouter Internet Inference Inference
  8. tRPC ʹ͓͚Δ Typesafe - ϓϩγʔδϟ (= ؔ਺) ͷίʔυ͔ΒΫϥΠΞϯτܕఆٛΛਪ࿦͢Δ Zod ΋಺෦

    DSL ͱͯ͠ར༻͞Ε͍ͯΔ - Mapped types / Conditional types Λ༻͍ͨܕਪ࿦ https://github.com/trpc/trpc/blob/b18b8134eb666e2c88fe3c245ebf78e7c9817859/packages/server/src/ core/types.ts#L53-L66
  9. Prisma - 2019 ೥ࠒʹొ৔ͨ͠ TypeScript ( Node.js ) ༻ͷ ORM

    ※ લ਎Ͱ͋ΔGraphQLϕʔεͷ Prisma v1 ͱ͸ผ෺ͱଊ͑ͯΑ͍ - Typesafe ͳΫΤϦͷهड़͕Մೳ - ֤छRDB ( MySQL / PostgreSQL / SQLite / SQLServer) ʹରԠ - ϚΠάϨʔγϣϯ༻ͷ CLI ΋෇ଐ͢Δ - ϥϯλΠϜͰಈ࡞͢ΔΫΤϦΤϯδϯ͸ Rust ੡
  10. const productDetail = procedure .input(z.object({ id: z.string() })) .query(async ({

    ctx: { prisma }, input: { id } }) => { const result = await prisma.product.findUnique({ where: { id } }) return { id: result.id, name: result.name, price: result.price, } }) Node.js Database generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model Product { id String @id @default(cuid()) name String @unique price Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } Generate Import schema.prisma (DSL) Prisma Client .js / .d.ts file
  11. Prisma ͱ TypeScript - ֎෦DSL (Schema) ͔ΒɺTypeScript ιʔείʔυΛࣗಈੜ੒͢Δઓུ - ͜ͷҙຯͰ͸ɺGraphQL

    ΍ Open API ͷΤίγεςϜʹ͍ۙ͠ - ίʔυੜ੒ʹ CLI ࣮ߦ͕ඞཁͱͳΔ͕ɺੜ੒෺ࣗମ͸ಡΈ΍͍͢ - tRPC ΍ Zod ͷ৔߹, ਪ࿦աఔͷܕ৘ใ͕ෳࡶͰܕύζϧΈ͕ڧ͍
  12. ·ͱΊ - T3 Axiom Ͱ͋Δ "Typesafety is not optional" Λେࣄʹ͠·͠ΐ͏

    - Typesafety ΛಘΔ͜ͱ ≒ unknown Λ౗͢͜ͱ - TypeScript ܕਪ࿦ύλʔϯ: Zod, tRPC, react-hook-form, etc... - .ts ίʔυࣗಈੜ੒ύλʔϯ: Prisma, Relay, graphql-codegen, etc...
  13. ͓·͚ - TypeScript ϑϨϯυϦͳελοΫ͸ T3 Ҏલʹ΋৭ʑ͋Δ͕ɺͲ͜ʹ৽ نੑ͕͋Δͷ͔ - tRPC ؚΊɺZod

    Λத৺ʹਾ͑ͨΤίγεςϜ͕৳ͼ͍ͯΔ https://2022.stateofjs.com/en-US/other-tools/