4 คะแนน โดย GN⁺ 2 시간 전 | 2 ความคิดเห็น | แชร์ทาง WhatsApp
  • TypeScript 7.0 เป็นรีลีสที่ย้าย toolchain ไปเป็นเนทีฟโค้ดที่อิง Go โดยให้ความเร็วเพิ่มขึ้นโดยทั่วไป 8~12 เท่า สำหรับการบิลด์ทั้งหมดของโปรเจกต์ขนาดใหญ่
  • tsc ตัวใหม่ยังติดตั้งผ่านแพ็กเกจ typescript บน npm เหมือนเดิม และการรองรับในเอดิเตอร์ทำงานผ่าน language server แบบ LSP ใน VS Code, Visual Studio, WebStorm และอื่น ๆ
  • เวลาในการบิลด์ลดลงอย่างมากในโค้ดเบสอย่าง vscode, sentry, bluesky, playwright, tldraw และในบางสภาพแวดล้อม การใช้หน่วยความจำรวม ก็ลดลงด้วย
  • TypeScript 7.0 ยังไม่มี Programming API ที่เสถียร ดังนั้นเครื่องมือที่ฝัง TypeScript อยู่ภายใน เช่น typescript-eslint, Vue, MDX, Astro, Svelte และการตรวจชนิดของเทมเพลต Angular ยังจำเป็นต้องใช้ TypeScript 6.0 ควบคู่กันไป
  • มีค่าเริ่มต้นใหม่และตัวเลือกที่ถูกถอดออก จึงควรปรับใช้การเปลี่ยนแปลงของ TypeScript 6.0 ก่อนเพื่อให้ย้ายได้ง่ายขึ้น และมีแผนจะออก API ใหม่ใน TypeScript 7.1

Native TypeScript ที่อิง Go

  • TypeScript 7.0 เป็น native port ของ TypeScript toolchain โดยใช้โค้ดเบสใหม่ที่เขียนด้วย Go
  • การพอร์ตทำโดยพยายามคงโครงสร้างและตรรกะของโค้ดเบสเดิมไว้ให้มากที่สุด เพื่อให้ผลลัพธ์ระหว่างคอมไพเลอร์ทั้งสองมี ความสอดคล้อง และความเข้ากันได้
  • โค้ดเบสใหม่นี้ให้ผลลัพธ์ที่เร็วขึ้นโดยทั่วไป 8~12 เท่า ในการบิลด์ทั้งหมด ด้วยความเร็วของเนทีฟโค้ด, มัลติเธรดดิ้งบน shared memory และการปรับแต่งหลายด้าน
  • การติดตั้งยังทำผ่าน npm ได้เหมือนเดิม
npm install -D typescript
  • หลังติดตั้งแล้ว จะสามารถใช้ไฟล์รัน tsc ตัวใหม่ใน workspace ได้ และรันผ่าน npx tsc ได้

ลดระยะเวลาของ feedback loop ในการพัฒนา

  • TypeScript มีส่วนเกี่ยวข้องกับหลายขั้นตอนของการพัฒนา เช่น การโหลดเอดิเตอร์, การค้นหา reference ทั้งหมด, autocomplete, diagnostics, tsc และโหมด --watch
  • TypeScript 7 ช่วยลดเวลารอในกระบวนการทั้งหมดนี้ ทำให้ feedback loop สั้นลง
  • ในโค้ดเบสของ VS Code เวลาตั้งแต่เปิดไฟล์ที่มีข้อผิดพลาดจนเห็นข้อผิดพลาดแรก ลดลงจากประมาณ 17.5 วินาที เหลือต่ำกว่า 1.3 วินาที เร็วขึ้นมากกว่า 13 เท่า
  • การรองรับในเอดิเตอร์อิง LSP และ language server ตัวใหม่ใช้มัลติเธรดดิ้งเพื่อจัดการคำขอพร้อมกันได้เร็วขึ้น
  • ผู้ใช้ VS Code สามารถติดตั้ง ส่วนขยายเฉพาะสำหรับ TypeScript 7 ได้ และภายในไม่กี่สัปดาห์ข้างหน้า VS Code เองก็มีกำหนดรวมการรองรับ TypeScript 7 มาให้
  • Visual Studio เวอร์ชันล่าสุดจะเปิดใช้ TypeScript 7 ให้อัตโนมัติตาม workspace

ประสิทธิภาพการบิลด์และผลด้านหน่วยความจำ

  • เวลาในการบิลด์ทั้งหมดเมื่อเทียบระหว่าง TypeScript 6 และ 7 บนโค้ดเบสโอเพนซอร์สขนาดใหญ่ มีดังนี้
โค้ดเบส TypeScript 6 TypeScript 7 ความเร็วที่เพิ่มขึ้น
vscode 125.7 วินาที 10.6 วินาที 11.9 เท่า
sentry 139.8 วินาที 15.7 วินาที 8.9 เท่า
bluesky 24.3 วินาที 2.8 วินาที 8.7 เท่า
playwright 12.8 วินาที 1.47 วินาที 8.7 เท่า
tldraw 11.2 วินาที 1.46 วินาที 7.7 เท่า
  • ในการบิลด์ชุดเดียวกัน TypeScript 7 ยังมีแนวโน้มใช้ หน่วยความจำรวม น้อยลงด้วย
โค้ดเบส TypeScript 6 TypeScript 7 การเปลี่ยนแปลงของหน่วยความจำ
vscode 5.2GB 4.2GB -18%
sentry 4.9GB 4.6GB -6%
bluesky 1.8GB 1.3GB -26%
playwright 1.0GB 0.9GB -11%
tldraw 0.6GB 0.5GB -15%

การยืนยันกับโค้ดเบสจริงและฟีดแบ็กจากทีม

  • โปรเจกต์ TypeScript รัน เทสต์หลายหมื่นรายการ ที่สะสมมานานกว่า 10 ปี กับทุกคอมมิตบนสาขา main
  • นอกเหนือจากเทสต์เหล่านี้ TypeScript 7 ยังได้รับการตรวจสอบกับโค้ดเบสจริงของทีมขนาดใหญ่ทั้งภายในและภายนอก
  • ภายใน Microsoft มีทีม Loop, Office, PowerBI, Teams และ Xbox ที่ตรวจสอบ TypeScript 7
  • ภายนอกมี Bloomberg, Canva, Figma, Google, Lattice, Linear, Miro, Notion, Sentry, Slack, Vanta, Vercel, VoidZero และอื่น ๆ ที่ทดสอบบนโค้ดเบสของตนและให้ฟีดแบ็ก
  • language server ตัวใหม่ลดคำสั่ง language server ที่ล้มเหลวได้ มากกว่า 80% และลด server crash ได้ มากกว่า 60% เมื่อเทียบกับ TypeScript 6.0
  • ตัวอย่างฟีดแบ็กจากทีมจริงมีดังนี้
    • Slack ระบุว่าเมื่อใช้ TypeScript 7 เวลาใน merge queue ลดลง 40% และเวลาในการตรวจชนิดใน CI ลดลงจากประมาณ 7.5 นาทีเหลือ 1.25 นาที
    • Vanta พบว่าหนึ่งในโปรเจกต์ขนาดใหญ่ของตนมีความเร็วในการบิลด์เพิ่มขึ้นสูงสุด 9 เท่า
    • ทีม Microsoft News Services ลดเวลารอ CI build ได้ 400 ชั่วโมงต่อเดือน
    • Canva ระบุว่าเวลาจนเห็นข้อผิดพลาดแรกในเอดิเตอร์ลดลงจากประมาณ 58 วินาทีเหลือ 4.8 วินาที

การใช้งานควบคู่กับ TypeScript 6.0

  • TypeScript 7.0 ยังไม่รวม API
  • มีแผนจะให้ API ใหม่ที่แตกต่างออกไปใน TypeScript 7.1
  • จนกว่าจะถึงตอนนั้น สามารถรัน TypeScript 6.0 และ 7.0 ควบคู่กันได้สำหรับเครื่องมือที่ต้องการการเข้าถึงคอมไพเลอร์ในเชิงโปรแกรม
  • แพ็กเกจสำหรับความเข้ากันได้ตัวใหม่ @typescript/typescript6 มีไฟล์รัน tsc6 และ re-export API ของ TypeScript 6.0
  • สำหรับเครื่องมืออย่าง typescript-eslint ที่ import typescript โดยตรงในฐานะ peer dependency แนะนำให้ใช้ npm alias
npm install -D typescript@npm:@typescript/typescript6
  • หากต้องการใช้ TypeScript 6 API ร่วมกับ tsc ของ TypeScript 7 สามารถตั้ง alias ได้ดังนี้
{
  "devDependencies": {
    "@typescript/native": "npm:typescript@^7.0.2",
    "typescript": "npm:@typescript/typescript6@^6.0.2"
  }
}
  • แพ็กเกจ @typescript/native-preview เดิมเคยให้ nightly build ของโค้ดเบสใหม่ใน TypeScript 7 และมียอดดาวน์โหลดต่อสัปดาห์ มากกว่า 8.5 ล้านครั้ง
  • ต่อจากนี้ nightly build จะกลับมาเผยแพร่ผ่านแท็ก next ของแพ็กเกจ typescript มาตรฐาน
npm install -D typescript@next

ตัวเลือกควบคุมการทำงานแบบขนาน

  • TypeScript 7.0 รันหลายขั้นตอนแบบ ขนาน เช่น parsing, type checking และ emit

  • parsing และ emit แยกทำงานเป็นรายไฟล์ได้ง่าย จึงขยายได้บนโค้ดเบสขนาดใหญ่ด้วย overhead ที่ค่อนข้างต่ำ

  • แฟลกเชิงทดลองตัวใหม่ --checkers, --builders, --singleThreaded ใช้ปรับพฤติกรรมการทำงานแบบขนาน

  • --checkers

    • TypeScript 7.0 จะสร้าง worker สำหรับ type checking ตามจำนวนคงที่ และแบ่งงานกับไฟล์อินพุตเดียวกันแบบเดิมเสมอ เพื่อให้ได้ผลลัพธ์เหมือนกันทุกครั้ง
    • จำนวน worker สำหรับ type checking โดยค่าเริ่มต้นคือ 4 ตัว และปรับได้ด้วย --checkers
    • ผลลัพธ์บนเครื่องเดียวกันเมื่อใช้ --checkers 8 มีดังนี้
    โค้ดเบส TypeScript 6 TypeScript 7 --checkers 8 ความเร็วที่เพิ่มขึ้น
    vscode 125.7 วินาที 7.51 วินาที 16.7 เท่า
    sentry 139.8 วินาที 12.08 วินาที 11.6 เท่า
    bluesky 24.3 วินาที 2.01 วินาที 12.1 เท่า
    playwright 12.8 วินาที 1.16 วินาที 11 เท่า
    tldraw 11.2 วินาที 1.06 วินาที 10.6 เท่า
  • การเพิ่ม --checkers อาจช่วยให้ใช้ CPU core ได้มากขึ้นและทำให้บิลด์เร็วขึ้น แต่โดยทั่วไปมักมาพร้อมกับ การใช้หน่วยความจำที่เพิ่มขึ้น

    • ใน CI runner ที่มี CPU core และหน่วยความจำน้อย สามารถลดค่านี้ลงเพื่อหลีกเลี่ยง overhead ที่ไม่จำเป็นได้
    • --checkers 1 จะทำให้การตรวจสอบ type กลายเป็นแบบ single-threaded แทบทั้งหมด และลดงานที่ซ้ำซ้อน
    • ในบางกรณีที่พบได้น้อย การเปลี่ยนจำนวน --checkers อาจเผยให้เห็นผลลัพธ์ที่ขึ้นกับลำดับการทำงาน ดังนั้นการกำหนดจำนวน checker แบบตายตัวให้เหมือนกันทั้งสภาพแวดล้อมการบิลด์อาจช่วยได้
  • --builders

    • --builders ใช้ควบคุมจำนวน project reference builder ที่สามารถรันพร้อมกันได้เมื่อใช้ --build
    • อาจมีประโยชน์อย่างมากโดยเฉพาะใน monorepo ที่มีหลายโปรเจ็กต์
    • การเพิ่มค่านี้อาจทำให้บิลด์เร็วขึ้น แต่ก็อาจเพิ่มการใช้หน่วยความจำด้วย
    • มีผลแบบคูณร่วมกับ --checkers ดังนั้น --checkers 4 --builders 4 อาจทำให้มี ตัวตรวจสอบ type สูงสุด 16 ตัว ทำงานพร้อมกันได้
    • ต่างจาก --checkers การเปลี่ยนจำนวน --builders ไม่ควรทำให้ผลลัพธ์เปลี่ยนไป
    • การบิลด์แบบ project reference โดยพื้นฐานแล้วมักติดคอขวดจาก dependency graph ของโปรเจ็กต์
  • --singleThreaded

    • --singleThreaded จะทำให้คอมไพเลอร์ทั้งหมดทำงานบนเธรดเดียว
    • อาจมีประโยชน์สำหรับการดีบัก การเปรียบเทียบประสิทธิภาพระหว่าง TypeScript 6 และ 7 การ orchestration การบิลด์แบบขนานจากภายนอก และสภาพแวดล้อมที่ทรัพยากรถูกจำกัดอย่างมาก
    • แฟลกนี้ไม่ได้จำกัดเพียงให้จำนวน worker สำหรับตรวจสอบ type เหลือ 1 เท่านั้น แต่ยังทำให้การ parsing และ emit ทำงานบนเธรดเดียวด้วย

โหมด --watch ใหม่

  • TypeScript 7 ได้สร้างโหมด --watch ขึ้นมาใหม่ทั้งหมด
  • --watch แบบใหม่มอบความสามารถในการเฝ้าดูไฟล์ข้ามแพลตฟอร์มที่มีประสิทธิภาพและเสถียร โดยอิงจาก file-watcher ของ Parcel bundler
  • Go standard library ไม่มี API สำหรับเฝ้าดูไฟล์ในตัว และไลบรารี third-party ที่พิจารณาก็มีปัญหาในด้านความเสถียร ประสิทธิภาพ การรองรับข้ามแพลตฟอร์ม และการผสานเข้ากับเครื่องมือบิลด์
  • วิธีแบบ polling ล้วน ๆ ใช้งานได้บนหลายระบบปฏิบัติการ แต่มีต้นทุนการประมวลผลสูงในโปรเจ็กต์ขนาดใหญ่ที่มี dependency ใน node_modules จำนวนมาก
  • ทีม TypeScript ได้นำ @parcel/watcher ที่ใช้ใน VS Code มา port เป็น Go และใช้ assembly shim ขนาดเล็กที่สุดเพื่อหลีกเลี่ยงการพึ่งพา C++ toolchain
  • watcher นี้เป็นแพ็กเกจแยกอิสระ และนำไปสู่ การปรับปรุงการใช้ทรัพยากร บนหลายแพลตฟอร์มในโหมด --watch ของ TypeScript 7

ค่าเริ่มต้นของ TypeScript 6.0 และการเปลี่ยนแปลงด้านความเข้ากันได้

  • TypeScript 7.0 ถูกออกแบบมาให้เข้ากันได้กับการตรวจสอบ type และพฤติกรรมบรรทัดคำสั่งของ TypeScript 6.0
  • โค้ดที่คอมไพล์ผ่านอย่างสะอาดบน TypeScript 6.0 โดยเปิดแฟลก stableTypeOrdering และไม่ได้ตั้งค่า ignoreDeprecations ควรคอมไพล์ได้แบบเดียวกันบน TypeScript 7.0
  • TypeScript 7.0 นำค่าเริ่มต้นใหม่ของ TypeScript 6.0 มาใช้ และจะรายงาน hard error กับแฟลกและไวยากรณ์ที่ถูก deprecated ใน TypeScript 6.0
  • การเปลี่ยนแปลงค่าเริ่มต้นหลักมีดังนี้
    • ค่าเริ่มต้นของ strict คือ true
    • ค่าเริ่มต้นของ module คือ esnext
    • ค่าเริ่มต้นของ target คือ ECMAScript เวอร์ชันเสถียรปัจจุบันที่อยู่ก่อน esnext
    • ค่าเริ่มต้นของ noUncheckedSideEffectImports คือ true
    • ค่าเริ่มต้นของ libReplacement คือ false
    • ค่าเริ่มต้นของ stableTypeOrdering คือ true และไม่สามารถปิดได้
    • ค่าเริ่มต้นของ rootDir คือ ./
    • ค่าเริ่มต้นของ types คือ [] และสามารถคืนค่าพฤติกรรมเดิมได้ด้วย ["*"]
  • การเปลี่ยนแปลงของ rootDir และ types ถูกมองว่าอาจเป็นการเปลี่ยนแปลงที่น่าประหลาดใจที่สุด
    • โปรเจ็กต์ที่มี tsconfig.json อยู่นอกไดเรกทอรีซอร์สอย่าง src จำเป็นต้องระบุ rootDir อย่างชัดเจนเพื่อคงโครงสร้างไดเรกทอรีเดิมไว้
    • โปรเจ็กต์ที่พึ่งพา global declaration บางตัวจำเป็นต้องระบุแพ็กเกจ @types ที่ต้องใช้ไว้ใน types
{
  "compilerOptions": {
    "rootDir": "./src"
  },
  "include": ["./src"]
}
{
  "compilerOptions": {
    "types": ["node", "jest"]
  }
}

พฤติกรรมที่ถูกลบออกหรือกลายเป็น hard error

  • ใน TypeScript 7.0 ตัวเลือกและไวยากรณ์หลายรายการที่ถูก deprecated ใน TypeScript 6.0 จะไม่ได้รับการรองรับอีกต่อไป
  • รายการหลักมีดังนี้
    • ไม่รองรับ target: es5
    • ไม่รองรับ downlevelIteration
    • ไม่รองรับ moduleResolution: node/node10 และแนะนำ nodenext กับ bundler
    • ไม่รองรับ module: amd, umd, systemjs, none และแนะนำ esnext หรือ preserve ร่วมกับการ resolve โมดูลแบบ bundler หรือแบบเบราว์เซอร์
    • ไม่รองรับ baseUrl โดย paths สามารถอัปเดตให้ใช้ relative path อิงจากรากของโปรเจ็กต์แทน baseUrl ได้
    • ไม่รองรับ moduleResolution: classic และแนะนำ bundler หรือ nodenext
    • ไม่สามารถตั้ง esModuleInterop และ allowSyntheticDefaultImports เป็น false ได้
    • alwaysStrict จะถือว่าเป็น true และไม่สามารถตั้งเป็น false ได้
    • ไม่สามารถใช้คีย์เวิร์ด module ในการประกาศ namespace ได้
    • ไม่สามารถใช้คีย์เวิร์ด asserts ใน import ได้ และต้องใช้ with ให้สอดคล้องกับการเปลี่ยนแปลงของไวยากรณ์ ECMAScript import attribute
    • ภายใต้ skipDefaultLibCheck คำสั่ง /// <reference no-default-lib /> จะไม่ได้รับการเคารพอีกต่อไป
    • หากมี tsconfig.json อยู่ในไดเรกทอรีปัจจุบัน จะไม่สามารถรับ file path ในการบิลด์ผ่านบรรทัดคำสั่งได้ และต้องระบุ --ignoreConfig อย่างชัดเจน

การเปลี่ยนแปลงของ template literal type และการรองรับ JavaScript

  • TypeScript 7.0 จัดการ Unicode code point ในการอนุมาน template literal type ได้เป็นธรรมชาติมากขึ้น
type HeadTail<S> = S extends `${infer Head}${infer Tail}` ? [Head, Tail] : never;

type Result = HeadTail<"😀abc">;
// 7.0: ["😀", "abc"]
// ก่อนหน้า: ["\ud83d", "\ude00abc"]
  • ก่อนหน้านี้ ระบบจะอิงตามพฤติกรรม UTF-16 indexing ของ JavaScript และแยก "😀" ออกเป็นสองส่วนของ surrogate pair
  • พฤติกรรมใหม่นี้สอดคล้องกับความเข้าใจแบบธรรมชาติที่มอง "😀" เป็นหนึ่งหน่วย เหมือน for...of หรือ [...str]
  • การจัดการสตริงระดับ type ที่ตั้งใจจำลอง UTF-16 code unit โดยตรงอาจได้รับผลเป็น breaking change
  • การรองรับ JavaScript ได้ถูกปรับใหม่ให้สอดคล้องกับวิธีวิเคราะห์ไฟล์ TypeScript มากขึ้น
    • ไม่สามารถใช้ค่าในตำแหน่งของ type ได้ และต้องใช้ typeof someValue
    • @enum จะไม่ได้รับการปฏิบัติเป็นกรณีพิเศษอีกต่อไป
    • ไม่สามารถใช้ ? เดี่ยว ๆ เป็น type ได้ และควรใช้ any
    • @class จะไม่ทำให้ฟังก์ชันกลายเป็น constructor และควรใช้การประกาศ class
    • ไม่รองรับ postfix !
    • ต้องนิยามชื่อ type ภายในแท็ก @typedef
    • ไม่รองรับไวยากรณ์ฟังก์ชันแบบ Closure อีกต่อไป และควรใช้ไวยากรณ์ย่อของ TypeScript
  • JavaScript pattern บางอย่าง เช่นการ aliasing ของ this และการกำหนด prototype ของฟังก์ชันใหม่ทั้งก้อน ก็จะไม่ได้รับการปฏิบัติเป็นกรณีพิเศษอีกต่อไป
  • ความแตกต่างระหว่าง TypeScript 6.0 และ 7.0 มีการสรุปไว้อย่างละเอียดเพิ่มเติมใน CHANGES.md

ฟีเจอร์และข้อจำกัดของตัวแก้ไข

  • TypeScript 7.0 ได้เพิ่มฟีเจอร์ของตัวแก้ไขหลายอย่างที่ขาดหายไปหลังจากช่วง beta
  • รวมถึง auto import, hover ที่ขยายได้, inlay hint, code lens, go-to-source-definition, JSX linked editing และ tag completion
  • ฟีเจอร์ที่หายไปจาก TypeScript 7.0 beta อย่าง semantic highlighting, “sort imports”, “remove unused imports” เป็นต้น ก็ถูกเพิ่มเข้ามาด้วย
  • เพื่อคุณภาพของ language server ได้มีการสร้างโครงสร้างพื้นฐานสำหรับการทดสอบและการวินิจฉัยใหม่ และสามารถทำ fuzz test กับโค้ดเบส TypeScript·JavaScript หลักบน GitHub ได้

ข้อจำกัดปัจจุบันของเวิร์กโฟลว์ภาษาแบบฝังตัว

  • เวิร์กโฟลว์ที่ใช้ Vue, MDX, Astro, Svelte เป็นต้น มีแนวโน้มว่ายังไม่สามารถใช้ TypeScript 7 ได้
  • การตรวจสอบชนิดของเทมเพลตแบบพิเศษ เช่น Angular template ก็มีแนวโน้มว่าจะยังใช้ TypeScript 7 ไม่ได้
  • เหตุผลหลักคือ TypeScript 7 ยังไม่เปิดเผย Programming API ที่เสถียร
  • เครื่องมือที่ฝัง TypeScript เข้าไปในคอมไพเลอร์และ language service ของตัวเอง เช่น Volar ในตอนนี้จึงยังต้องพึ่งพา TypeScript 6.0
  • ทีม TypeScript มองว่านี่เป็นข้อจำกัดเฉพาะช่วงเวลา และมีแผนจะร่วมมือกับผู้ดูแลโครงการเหล่านั้นเพื่อให้รองรับ TypeScript 7
  • จนกว่าจะถึงตอนนั้น แนะนำให้ใช้ TypeScript 7 ในกรณีที่ไม่ต้องใช้ language server plugin
  • โปรเจกต์ Angular สามารถใช้ tsc ของ TypeScript 7 จาก CLI เพื่อจับข้อผิดพลาดทั้งโปรเจกต์ได้อย่างรวดเร็ว และใช้ TypeScript 6.0 ควบคู่กันไปสำหรับการรองรับในตัวแก้ไข
  • Vue, MDX, Astro, Svelte เป็นต้น จะยังต้องใช้ TypeScript 6.0 ต่อไปอีกระยะหนึ่ง
  • ใน VS Code สามารถย้อนกลับไปใช้ TypeScript 6.0 ได้ด้วยคำสั่ง “Disable TypeScript 7 Language Server”

แผนในอนาคต

  • การออก TypeScript 7.0 เป็นหมุดหมายสำคัญของ native port ที่โปรเจกต์ TypeScript ทุ่มเททำมาเป็นเวลากว่า 1 ปี
  • หลัง 7.0 จะกลับไปทำฟีเจอร์ใหม่ ปรับปรุงการใช้งาน ปรับปรุงประสิทธิภาพเพิ่มเติม และพัฒนา API ใหม่สำหรับ ecosystem
  • คาดว่าจะออกฟีเจอร์รีลีสใหม่ ทุก 3~4 เดือน เช่นเดียวกับช่วงก่อน TypeScript 7.0
  • TypeScript 7.1 มีแผนจะอุดช่องว่างเพื่อช่วยให้ชุมชนเปลี่ยนผ่านได้ง่ายขึ้น และนำเสนอ API ใหม่

2 ความคิดเห็น

 
GN⁺ 2 시간 전
ความคิดเห็นจาก Hacker News
  • ตัวเลขการเพิ่มความเร็วของ TypeScript 7 ตามการทดสอบของทีมเองมีดังนี้

    Codebase TypeScript 6 TypeScript 7 Speedup
    vscode 125.7s 10.6s 11.9x
    sentry 139.8s 15.7s 8.9x
    bluesky 24.3s 2.8s 8.7x
    playwright 12.8s 1.47s 8.7x
    tldraw 11.2s 1.46s 7.7x

    ทีมที่ทำผลงานได้ระดับนี้พร้อมกับ migrate อย่างรับผิดชอบนี่น่าทึ่งมาก หวังว่า Bun จะดูไว้เป็นบทเรียนบ้าง สิ่งที่สงสัยคือจะส่งผลอย่างไรกับเครื่องมือชั้นล่างที่ต้อง build codebase ของ TypeScript อย่าง tsdown หรือ esbuild และสามารถใช้ TS 7 ร่วมกับ tsdown ปัจจุบันได้ไหม

    • esbuild ไม่พึ่งพา TypeScript เลยจึงไม่มีปัญหา ส่วน tsdown ขึ้นอยู่กับว่าใช้ --isolatedDeclarations หรือไม่ ถ้าไม่ใช้ ก็แค่ติดตั้ง TypeScript 6 ควบคู่กันตามคำแนะนำในบล็อก
    • สงสัยว่ามองว่าการ migrate ของ Bun ไม่รับผิดชอบหรือเปล่า
  • เมื่อก่อนก็เคยมีช่วงที่ถกเถียงกันว่า type ไม่คุ้มค่ากับความพยายามที่ต้องลงไป สิ่งที่ทำให้ TypeScript ดี เหนือสิ่งอื่นใด คือการทำให้ type กลายเป็นเรื่องแพร่หลาย

    • จำไม่ค่อยได้ว่ามีใครเกลียด type จริง ๆ สิ่งที่หลายคนไม่ชอบคือ static typing หรือพูดให้แม่นกว่าคือ typing แบบ static และ explicit
      เช่น เคยได้ยินหลายครั้งว่าประมาณว่า Python ใช้ไม่ได้เพราะไม่มี type ซึ่งไม่สมเหตุสมผลเลย Python เป็นภาษาแบบ strongly typed และในขณะเดียวกันก็เป็นภาษาแบบ dynamically typed เท่านั้นเอง
      มีภาษาที่ไม่มี type จริง ๆ หรือที่มักเรียกว่า “stringly typed” อยู่เหมือนกัน AREXX ที่เคยลองเล่นตอนเด็ก ๆ แม้ค่าจะดูเหมือนตัวเลขแต่ทุกค่าก็เป็นสตริง และเครื่องมือ Unix CLI ส่วนใหญ่แบบ sed ก็อาจมองได้แบบนั้น แต่ข้อถกเถียงเรื่อง type ส่วนใหญ่ล้อมรอบภาษา dynamic typing อย่าง Python และแทบไม่เคยเห็นใครบอกว่าภาษา weakly typed หรือ untyped เหมาะกับโปรเจกต์ขนาดใหญ่เลย กลับกัน ได้ยินบ่อยว่าคนเรียก Python ผิด ๆ ว่า “ไม่มี type” แล้วบอกว่าใช้กับโปรเจกต์ขนาดใหญ่ไม่ได้ ซึ่งสำหรับคนที่กำลังทำโปรเจกต์ใหญ่ด้วย Python จริง ๆ แล้วชวนสับสนมาก
    • type system สมัยก่อนมันไม่ค่อยดีเฉย ๆ การถูกบังคับให้ใช้ class hierarchy เพื่อแสดง type แบบ “OR” อย่าง sum types นั้นทรมานมาก ภาษาใหม่ ๆ ที่มี sum types อย่าง TypeScript, Rust, Swift, Kotlin ใช้แล้วสบายกว่ามาก
    • โดยส่วนตัวเคยคุยกับคนที่พูดแทบจะตรง ๆ ว่า “ไม่เคยเจอ typing error ใน JavaScript เลย” อยู่สามครั้ง ในจำนวนนั้นสองคนเป็นคนที่ผม/ฉันเคารพงานของเขา จึงเข้าใจได้ยากว่าทำไมถึงมีมุมมองแบบนั้นได้
    • คิดว่า algebraic data types กับ pattern matching เป็นตัวเปลี่ยนเกม ไม่ต้องไปไกลถึงระดับ Haskell ก็ทำให้ type มีประโยชน์ขึ้นมากอย่างฉับพลัน
      เมื่อก่อนการได้สัมผัส type ส่วนใหญ่คือ C++/Java และโดยเฉพาะ C++ แทบจะเป็นตัวอย่างที่ดีของอะไรไม่ได้ นอกจากวิธีสร้างภาษาที่ซับซ้อนเกินไป พอได้เห็นการใช้ type ที่ดีจริง ๆ สักครั้ง ก็โน้มน้าวได้ง่ายขึ้นมาก
    • ตอนนี้รอแค่ DependentTypeScript อยู่
  • สิ่งที่น่าประทับใจจริง ๆ ตรงนี้คือทีมที่ยอดเยี่ยมซึ่งดูแล codebase แยกกันสองชุดพร้อมกันเพื่อ type system ที่ก้าวหน้าที่สุดเท่าที่มนุษยชาติรู้จัก ตั้งตารอการเขียนใหม่ด้วย Rust ด้วย

    • ไม่แน่ใจว่าการเขียนใหม่ด้วย Rust จะมีความหมายไหม Go เขียนโค้ดได้เร็ว และดูโค้ดแล้ว implement TypeScript ใหม่แบบ 1:1 ได้ง่าย
      Rust น่าจะใช้เวลา development นานกว่ามาก แม้ Rust อาจเร็วกว่า Go ได้ 20% แต่แค่การปรับจาก TypeScript ไปเป็น Go ก็ให้ผลดีขึ้นมากพอแล้ว ใน vscode อาจได้ 14 เท่าด้วย Rust แทนที่จะเป็น 11 เท่าด้วย Go แต่แค่ Go ก็เพียงพอที่จะสร้างความแตกต่างได้มากแล้ว
    • ถึงอาจเรียกได้ว่าซับซ้อนที่สุด แต่ไม่แน่ใจว่าเป็น type system ที่ “ก้าวหน้าที่สุด” หรือไม่ ตำแหน่งนี้คงไม่มีคำตอบตายตัว แต่คิดว่าภาษาในกลุ่ม proof assistant สักภาษาน่าจะเป็นผู้สมัครที่สมเหตุสมผลกว่า
      ไม่ได้ตั้งใจจะลดคุณค่าของ type system ของ TypeScript และจริง ๆ แล้วมันเป็นงานที่น่าสนใจมาก
    • Steve Francia ผู้สร้าง Hugo และโปรเจกต์ Go สำคัญหลายตัว เคยเขียนบทความเกี่ยวกับ Go ในยุคของเอเจนต์ ไว้: https://spf13.com/p/go-the-agentic-language/
    • สงสัยว่า “type system ที่ก้าวหน้าที่สุดเท่าที่มนุษยชาติรู้จัก” หมายความว่าอะไรกันแน่
    • เท่าที่รู้ หลังจากพิจารณา Rust และตัวเลือกอื่น ๆ อย่างจริงจังแล้วจึง เลือก Go จำเหตุผลทั้งหมดไม่ได้ แต่ในบล็อกโพสต์เดิมมีอธิบายไว้ละเอียด
  • พอใช้ TypeScript มาหลายปีแล้ว การต้องใส่ type annotation เองใน Python และต้องดึงฟีเจอร์ภาษาพื้นฐานอย่าง abc มาใช้ รู้สึกยุ่งยากจริง ๆ

  • น่าสนใจ แต่ตอนนี้ Node ลบ type annotation ของ TypeScript ได้แบบ native แล้ว เลยแทบไม่ค่อยรัน TSC มีแค่เวลาทำ breaking change ใหญ่ ๆ แล้วต้องดู output แบบ static ของ compiler เพื่อเช็กว่ายังมีส่วนไหนที่อัปเดตไม่ครบเท่านั้น
    โค้ด frontend ที่จะไปยัง browser ก็พึ่งพาการลบ type ของ Node เช่นกัน

    • พูดถูก แต่ในอีกด้านหนึ่ง editor ก็รัน TypeScript language server อยู่ทั้งวันอยู่ดี CI ก็น่าจะเป็นแบบนั้น และ AI agent ก็น่าจะทำแบบนั้นก่อนจะมั่นใจกับงานที่เพิ่งทำไป
  • ดีใจที่ ไวยากรณ์ type ของ JSDoc ยังได้รับความสนใจต่อเนื่อง เป็นวิธีที่ชอบที่สุดในการใช้ TypeScript กับโปรเจกต์ส่วนตัว การเปลี่ยนไวยากรณ์บางอย่างอาจอัปเดตลำบาก แต่ส่วนใหญ่ดูเหมือนจะเป็นไปในทิศทางที่ดีขึ้น

  • ความเจ็บปวดใหญ่ของ TypeScript คือการปรับ ขอบเขตการตั้งค่า tsconfig อย่าง lib และ types สำหรับบางส่วนของโปรเจกต์ทำได้ยาก
    โปรเจกต์เป็นเว็บแอป แต่เพราะ vite.config.ts, Playwright และ unit test ทำให้ฝั่งเครื่องมือ IDE มี type ของ Node เข้ามาอยู่ด้วย ต่อให้เพิ่ม Node API ใน React component tsc ก็ไม่บ่น
    ตอนนี้ถ้าจะกั้น DOM library กับ Node library ออกจากกัน ต้องใช้ project references ที่ยุ่งเหยิง, tsconfig.json จำนวนมาก และไฟล์เอาต์พุต tsbuildinfo อีกเพียบ แถมการใช้ project references โดยหลีกเลี่ยงการปล่อย type output ก็ยุ่งยากด้วย

    • เห็นด้วยว่านี่เป็นจุดที่เจ็บปวดจริง ๆ ใช้ nx อยู่ ซึ่งช่วยจัดการเรื่องพวกนี้แทนให้ Playwright เป็นโปรเจกต์แยกที่มี tsconfig ของตัวเอง และทั้งหมดสืบทอดจาก root tsconfig
      แม้จะเป็นแอปพลิเคชันเดียวก็ยังชอบใช้ nx และย้ายโค้ดที่ใช้ร่วมกันไปเป็น “library” ใช้ library แบบไม่ต้อง build ซึ่งในโปรเจกต์ใหญ่ถือว่าค่อนข้างดี
  • ยังไม่มี TypeScript compiler API แต่บอกว่ากำลังทำอยู่ เลยตั้งตารอ

    • คาดว่าจะเข้ามาใน 7.1
  • พอเห็นกราฟที่การใช้หน่วยความจำลดลงและประสิทธิภาพเพิ่มขึ้นมาก ก็ทำให้คิดว่าฝั่งเซิร์ฟเวอร์ควรใช้ Go แทน TypeScript หรือเปล่า

    • ก่อนอื่น ฝั่งเซิร์ฟเวอร์ไม่ได้รัน TypeScript อยู่แล้ว ไม่ว่าจะใช้เอนจินรันแบบไหน ก็รันโค้ดที่แปลงแล้วหรือ JavaScript
      และทุกวันนี้ก็มีตัวเลือกอยู่แล้ว แต่ก็ไม่ค่อยเข้าใจว่าทำไมยังมีคนเริ่มโปรเจกต์ใหม่ด้วย TS/JS/Python
    • อาจเป็นเพราะสามารถ แชร์ type หรือ module กับโปรเจกต์ฟรอนต์เอนด์ได้ หรือในแอปพลิเคชันที่ไม่ได้ใช้ CPU หนัก ๆ แทบไม่มีความต่างก็ได้ และอาจเป็นเพราะคุ้นเคยและชอบด้วย อีกอย่างคือ ecosystem ของ library ใหญ่มาก
    • นี่คือ ประสิทธิภาพตอน build ไม่ใช่ประสิทธิภาพตอน runtime
    • ความแตกต่างด้านประสิทธิภาพระหว่าง Go กับ JS (เช่น Node) จะสำคัญหรือไม่ขึ้นอยู่กับ use case สำหรับ TypeScript compiler สำคัญแน่นอน แต่สำหรับแอป CRUD อาจไม่สำคัญเลย
    • เพราะถ้าเป็นไปได้ การทำงานด้วยภาษาหลักภาษาเดียวจะง่ายกว่า
  • ขอแสดงความยินดีกับทีม TypeScript มีเนื้อหาที่อยากเขียนยาว ๆ หรือทำเป็นเสียง แต่ถ้าพูดสั้น ๆ ecosystem ของ JavaScript/TypeScript คล้ายกับ การทำงานกับไม้
    จะทำไม้แผ่นลามิเนตราคาถูกหรือของสไตล์ Ikea ก็ได้ ถ้าเทียบกับโค้ดก็คงเป็นแอป vibe coding ที่ไม่มีความเป็นต้นฉบับ
    ในทางกลับกัน ก็ทำเฟอร์นิเจอร์ทำมือระดับพรีเมียมหรือตึกสูงโครงสร้างไม้ได้เช่นกัน แบบใช้ไม้ใหม่มาทำคานทนไฟด้วยเทคนิคการต่อประกอบเฉพาะและการลามิเนต ใน ecosystem ของ JavaScript/TypeScript ก็สามารถใช้ AI เหมือนเครื่องมือช่างทรงพลัง แต่ยังสร้างผลงานคุณภาพสูงด้วยจิตวิญญาณช่างฝีมือได้ ถ้ามีความกล้าที่จะสร้างและนำไปรัน ก็แค่ยอมรับ ecosystem ของ TypeScript/JavaScript

 
GN⁺ 2 시간 전
ความคิดเห็นใน Lobste.rs
  • เข้าใจเหตุผลอยู่ แต่ก็น่าสนใจที่ย้ายจาก คอมไพเลอร์ที่โฮสต์ตัวเอง ไปเป็นคอมไพเลอร์ที่ไม่ได้โฮสต์ตัวเอง
    โดยปกติแทบจะไปในทิศทางตรงกันข้ามเสมอ จึงเป็นแนวทางที่พบไม่บ่อย

    • ผมคิดว่าเราควรเห็นทิศทางแบบนี้บ่อยขึ้น ไม่ใช่ทุกภาษาจะเหมาะกับ การเขียนคอมไพเลอร์
      การโฮสต์ตัวเองสร้างแรงกดดันอย่างมากให้ภาษาพัฒนาไปเป็นภาษาที่เขียนคอมไพเลอร์ได้ดีขึ้น ซึ่งอาจไม่ใช่ทิศทางที่ถูกต้องเสมอไป
    • น่าประหลาดใจที่ผู้ออกแบบและผู้พัฒนาภาษาเข้าใจว่าภาษาของตัวเองไม่ได้สมบูรณ์แบบสำหรับทุกการใช้งาน
  • ถึงจะไม่ได้เขียนโค้ดด้วย TypeScript แต่ VSCode เองเขียนด้วย TypeScript เลยสงสัยว่าการปรับปรุงนี้จะส่งผลต่อ ความเร็วของ VSCode ด้วยไหม
    หรือส่งผลเฉพาะกับส่วนขยายภาษา TypeScript เท่านั้น

    • สิ่งที่เร็วขึ้นคือคอมไพเลอร์ ไม่ได้สร้างโค้ดที่เร็วขึ้นอย่างวิเศษ
    • มีผลเฉพาะกับ ส่วนขยายภาษา TypeScript เท่านั้น
    • TypeScript ถูกคอมไพล์เป็น JavaScript ตอนที่ VSCode ทำงาน node.js และ Chromium จะรัน โค้ด JavaScript
      สิ่งที่เร็วขึ้นตรงนี้มีเพียงคอมไพเลอร์ที่รับโค้ด TypeScript แล้วแปลงเป็น JavaScript และกระบวนการนี้เกิดขึ้นใน build pipeline ก่อนที่ Microsoft จะแจกจ่ายไฟล์รันของ VSCode
      ข้อยกเว้นที่เป็นไปได้คือเซิร์ฟเวอร์ TypeScript LSP อาจเร็วขึ้นด้วย เพราะมัน parse โค้ด TypeScript จริง ๆ ระหว่างรันอยู่ แต่เรื่องนี้แยกจากข้อเท็จจริงที่ว่า VSCode เขียนด้วย TypeScript
    • คอมไพเลอร์ TypeScript ไม่ได้ทำอะไรเยอะนัก จริง ๆ แล้ว tsc มีหลายอย่างที่ถูกทำเครื่องหมายเป็น WONTFIX เพราะหลักการคือไม่ควรไปแตะโค้ดที่กำลังประมวลผลอยู่ นอกจากขั้นต่ำอย่างการลบ type ออก
      ดังนั้นคาดว่าลักษณะด้านประสิทธิภาพของเครื่องมือที่สร้างด้วย TypeScript แทบจะไม่เปลี่ยนแปลง
  • เป็นทิปเล็ก ๆ ที่ผมได้มาเอง โปรเจกต์ที่ดูแลอยู่ตอนนี้ใช้ TS 5 แต่ตามคาด ผมไม่อยากใช้มันใน nvim
    เลยติดตั้ง TS 7 ด้วย mise ก่อน แล้วสร้าง symlink ชื่อ tsgo ใน node_modules/.bin ให้ชี้ไปยัง TS ที่ติดตั้งด้วย mise
    เพราะ nvim-lspconfig ยังใช้ชื่อไฟล์ tsgo แบบเก่าตั้งแต่ยุค technical preview อยู่ ทำให้ nvim ไปรัน TS 7 ที่ติดตั้งไว้แทน TS ในเครื่องโปรเจกต์