ตัวสร้างที่มีชนิดข้อมูลเข้มงวด
ออกแบบตัวสร้างแบบต่อสายที่สะสมตัวเลือกซึ่งมีชนิดข้อมูล ตรวจสอบขั้นตอนที่จำเป็นและชุดค่าผสมที่ถูกต้องด้วยเจเนอริกและชนิดข้อมูลแบบมีเงื่อนไข
ตัวสร้างที่มีชนิดข้อมูลเข้มงวด เป็นบทเรียน TypeScript Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน TypeScript Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส TypeScript Academy มีบทเรียนทั้งหมด 3 บทเรียน
บทนำ
เป้าหมาย: สร้าง APIs ที่เชื่อมต่อเป็นสายได้และเข้ารหัสความคืบหน้าไว้ในชนิดข้อมูล แต่ละขั้นจะส่งกลับสถานะใหม่ที่มีชนิดข้อมูลกำกับ จึงตรวจพบลำดับที่ไม่ถูกต้องขณะคอมไพล์
- สะสมตัวเลือกไว้ในเจเนอริก
- ควบคุมการเข้าถึงแต่ละขั้นด้วยแฟล็ก
- รักษา DX ให้เรียบง่าย
แฟล็กสถานะ
แต่ละขั้นจะส่งกลับชนิดข้อมูลสถานะใหม่ ส่วน build จะเรียกใช้ได้ก็ต่อเมื่อแฟล็กที่จำเป็นเป็นจริง
type Flags = { method: boolean; url: boolean }
type With<F extends Partial<Flags>> = { flags: F }
type True = true
type Builder<F extends Partial<Flags>, O extends Record<string, unknown>> = With<F> & {
method<M extends "GET" | "POST">(m: M): Builder<F & { method: True }, O & { method: M }>
url<U extends `/${string}`>(u: U): Builder<F & { url: True }, O & { url: U }>
build(this: Builder<{ method: True; url: True }, any>): O
}
function createBuilder(): Builder<{}, {}> {
return {
flags: {},
method(m) { return { ...this, flags: { ...this.flags, method: true }, method: this.method, url: this.url, build: this.build } as any },
url(u) { return { ...this, flags: { ...this.flags, url: true }, method: this.method, url: this.url, build: this.build } as any },
build() { return this as any }
} as any
}
const b = createBuilder()
const good = b.method("GET").url("/users").build() // ok
// const bad = b.build() // error: build requires method & url flagsสะสมตัวเลือก
สะสมตัวเลือกไว้ในเจเนอริก O โดยการเรียกแต่ละครั้งจะส่งกลับชนิดข้อมูลที่เพิ่มพร็อพเพอร์ตีใหม่เข้าไป
type B2<F extends Partial<Flags>, O extends Record<string, unknown>> = With<F> & {
header<K extends string, V extends string>(k: K, v: V): B2<F, O & { headers: Record<K, V> }>
query<K extends string, V extends string>(k: K, v: V): B2<F, O & { query: Record<K, V> }>
method<M extends "GET" | "POST">(m: M): B2<F & { method: True }, O & { method: M }>
url<U extends `/${string}`>(u: U): B2<F & { url: True }, O & { url: U }>
build(this: B2<{ method: True; url: True }, any>): O
}
function builder2(): B2<{}, {}> { return {} as any }
const conf = builder2()
.method("POST")
.url("/login")
.header("x-id", "42")
.query("next", "home")
.build()ชุดการผสมที่ถูกต้อง
จำกัดชุดการผสมด้วยชนิดข้อมูลแบบมีเงื่อนไข โดยอนุญาตให้ใช้ body ได้เฉพาะเมื่อเป็น POST
type Method = "GET" | "POST"
type BodyIfPost<M extends Method, B> = M extends "POST" ? { body: B } : {}
type B3<F extends Partial<Flags>, O extends Record<string, unknown>> = With<F> & {
method<M extends Method>(m: M): B3<F & { method: True }, O & { method: M }>
url<U extends `/${string}`>(u: U): B3<F & { url: True }, O & { url: U }>
body<B>(b: B & (O extends { method: "POST" } ? unknown : never)): B3<F, O & BodyIfPost<O extends { method: infer M } ? Extract<M, Method> : Method, B>>
build(this: B3<{ method: True; url: True }, any>): O
}
function builder3(): B3<{}, {}> { return {} as any }
const ok = builder3().method("POST").url("/u").body({ a: 1 }).build()
// const badBody = builder3().method("GET").url("/u").body({ a: 1 }).build() // compile-time errorไปป์ไลน์แบบแปรผันจำนวน
รวบรวมขั้นตอนเป็นชุดด้วยอาร์เรย์ทูเพิลแบบแปรผันจำนวน และจัดการข้อมูลนำเข้า/ส่งออกด้วย Parameters/ReturnType
type Step<A extends any[], R> = (...args: A) => R
type Pipeline<P extends Step<any, any>[]> = {
use<S extends Step<any, any>>(...s: [S]): Pipeline<[...P, S]>
run<A extends Parameters<P[0]>>(this: Pipeline<P>, ...args: A): ReturnType<P[number]>
}
function pipeMake(): Pipeline<[]> { return {} as any }
const pipe = pipeMake()
.use((a: string) => a.length)
.use((n: number) => n % 2 === 0)
// pipe.run("abc") // demo; implementation omittedเคล็ดลับ
เคล็ดลับ:
เก็บสถานะไว้ในเจเนอริกจำลอง อย่าเพิ่มภาระให้ขณะทำงาน
กำหนดชื่อขั้นตอนให้สั้นและตายตัว (method, url)
แยกชุดการผสมที่ซับซ้อนด้วยชนิดข้อมูลแบบมีเงื่อนไข เพื่อให้สายการทำงานสะอาดและเข้าใจง่าย
ตรวจสอบการกำกับลำดับของตัวสร้าง
ตรวจสอบอย่างรวดเร็ว: เราจะทำให้แน่ใจได้อย่างไรว่าเมธอด .method() ถูกเรียกก่อน .build()
ทบทวน
ทบทวน: ส่งต่อสถานะที่มีชนิดข้อมูลกำกับไปตามสายการทำงาน สะสมตัวเลือกในเจเนอริก และตรวจจับลำดับที่ไม่ถูกต้องขณะคอมไพล์
คำถามที่พบบ่อย
บทเรียน “ตัวสร้างที่มีชนิดข้อมูลเข้มงวด” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ตัวสร้างที่มีชนิดข้อมูลเข้มงวด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส TypeScript Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส TypeScript Academy มีบทเรียนทั้งหมด 3 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ตัวสร้างที่มีชนิดข้อมูลเข้มงวด”
ออกแบบตัวสร้างแบบต่อสายที่สะสมตัวเลือกซึ่งมีชนิดข้อมูล ตรวจสอบขั้นตอนที่จำเป็นและชุดค่าผสมที่ถูกต้องด้วยเจเนอริกและชนิดข้อมูลแบบมีเงื่อนไข คุณปฏิบัติ TypeScript Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน TypeScript Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน TypeScript Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน
บทเรียน “ตัวสร้างที่มีชนิดข้อมูลเข้มงวด” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน TypeScript Academy นี้ได้ไหม
ได้ บทเรียน TypeScript Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- สมาชิก rest ของทูเพิลและชนิดข้อมูลเคอร์รี
- ประกอบฟังก์ชันและอาร์กิวเมนต์อย่างปลอดภัย
- ตัวสร้างที่มีชนิดข้อมูลเข้มงวด