- มีการ merge PR #53725 ของ Node.js ทำให้รองรับการ รันไฟล์ TypeScript แบบทดลองผ่านแฟลก
--experimental-strip-types
- ฟีเจอร์นี้จะ ลบไวยากรณ์ของ type ออกจากซอร์ส TypeScript แล้วแปลงเป็นซอร์ส JavaScript โดย ไม่ทำการตรวจสอบ type ระหว่างการแปลง
- การติดตั้งใช้งานเริ่มต้นจะไม่ทำ การแปลงฟีเจอร์เฉพาะของ TypeScript อย่าง
Enum, namespaces เป็นต้น จึงจำกัดอยู่กับโค้ดที่เมื่อเอา type ออกแล้วกลายเป็น JavaScript ได้ทันที
- เลือกใช้
@swc/wasm-typescript สำหรับการติดตั้งใช้งาน เพราะมี ความเรียบง่าย โดยไม่ต้องเพิ่ม Rust หรือ Go เข้าไปใน toolchain ของ Node.js
- ในการอภิปรายมีการพูดถึงข้อจำกัดหลักอย่างกฎเรื่องนามสกุลไฟล์บังคับของ ESM, แนวปฏิบัติของ TypeScript ที่
import .js ทั้งที่ไฟล์จริงเป็น .ts, รวมถึงต้นทุนของ source map และตำแหน่งใน error stack
วิธีการทำงานของ --experimental-strip-types
- เมื่อเปิดใช้
--experimental-strip-types แล้ว Node.js จะสามารถ รันไฟล์ TypeScript ได้
- Node.js จะ transpile ซอร์สโค้ด TypeScript ให้เป็นซอร์สโค้ด JavaScript
- ระหว่างการ transpile จะ ไม่ทำ type checking และข้อมูล type จะถูกทิ้งไป
- ตัวอย่างมีดังนี้
const foo: string = "foo";
const foo = "foo";
เหตุผลที่เลือกแค่การลบ type และข้อจำกัดช่วงแรก
- แกนหลักของ PR นี้คือ การลบไวยากรณ์ type ออกจากไวยากรณ์ของ TypeScript
- runtime อื่นบางตัวอาจแปลงฟีเจอร์เฉพาะของ TypeScript ที่ไม่มีใน JavaScript เช่น
enum ให้เป็น JavaScript
- การติดตั้งใช้งานเริ่มต้นของ PR นี้จะไม่ทำการแปลงลักษณะนั้น
- ใช้
Enum ไม่ได้
- ใช้
namespaces ไม่ได้
- ฟีเจอร์เฉพาะของ TypeScript อื่น ๆ ก็ไม่อยู่ในขอบเขตการแปลง
- มีคำแนะนำให้ดูรายละเอียดการติดตั้งใช้งานและข้อจำกัดใน
typescript.md ของรายการเปลี่ยนแปลงใน PR
เลือก @swc/wasm-typescript เป็นเครื่องมือสำหรับการติดตั้งใช้งาน
@swc/wasm-typescript เป็น แพ็กเกจขนาดเล็ก ที่ประกอบด้วยไฟล์ wasm และไฟล์ JavaScript สำหรับ binding เข้าด้วยกัน
- เครื่องมืออื่นต้องการเพิ่ม Rust หรือ Go เข้าไปใน toolchain ของ Node.js
- SWC ถูกใช้ใน Deno เพื่อจุดประสงค์เดียวกันอยู่แล้ว และผู้เขียน PR มองว่านี่เป็น ตัวเลือกที่ผ่านการพิสูจน์แล้ว
- ในอนาคต ฟีเจอร์นี้อาจถูกติดตั้งใน ชั้น native ได้
- PR นี้อ้างอิง nodejs/loaders#217
การตีความ import และประเด็นเรื่องนามสกุลไฟล์
- import ที่ไม่ระบุนามสกุลไฟล์ อย่าง
import foo from "./foo" จะไม่ถูกรองรับ
- ใน ESM ของ Node.js มีกฎ mandatory file extensions อยู่แล้ว ดังนั้นการไม่รองรับ import แบบไม่มีนามสกุลจึงถูกมองว่าเป็นพฤติกรรมที่ตั้งใจไว้
- มีความเห็นว่าใน codebase แบบโมดูลของ TypeScript มักพบกรณีที่ในคำสั่ง import ใช้นามสกุล
.js ทั้งที่ไฟล์จริงเป็น .ts
- ตัวอย่าง:
import foo from './foo.js'
- ในระบบไฟล์จริงอาจไม่มี
./foo.js และมีแค่ ./foo.ts
- ผู้เขียน PR มองว่าปัญหานี้สามารถจัดการได้ในการทำงานรอบถัดไป และการเดานามสกุลไฟล์ต้องอาศัยการตรวจสอบระบบไฟล์เพิ่มและ heuristic
- ถ้าไม่มี
./foo.js ก็ตรวจ ./foo.ts
- ถ้าไม่มี
./foo.ts ก็ตรวจ ./foo.js
- การอภิปรายนี้ติดตามอยู่ใน nodejs/loaders#208
ตำแหน่งซอร์ส, source map และ error stack
- ในการรีวิวมีความเห็นว่าระยะสั้นจำเป็นต้องมี ตำแหน่งซอร์สที่แม่นยำ ใน error stack
- วิธีหนึ่งที่เป็นไปได้คือทำให้กระบวนการลบ type ไม่เปลี่ยนตำแหน่งในซอร์ส เพื่อ หลีกเลี่ยงการสร้างและการแมป source map
- มีการกล่าวถึงข้อจำกัดว่า source map มีต้นทุนทั้งด้านการใช้หน่วยความจำและประสิทธิภาพ และไม่ใช่เรื่องง่าย
- ผู้เขียน PR มองว่า SWC รองรับ source map อยู่แล้ว จึงอาจเพิ่มแฟลกสำหรับเปิดใช้งานได้
- อีกทางหนึ่งอาจขอให้ SWC รองรับตัวเลือกที่แทนไวยากรณ์ที่ถูกลบด้วยช่องว่าง เพื่อไม่ให้ error stack เดิมเปลี่ยนไป
ประเด็นด้านการออกแบบที่ยังเหลือก่อนทำให้เสถียร
- การรองรับ TypeScript แบ่งได้เป็น 2 แกน
- การลบไวยากรณ์ type
- การปรับกฎการตีความเพื่อให้รับไฟล์
.ts
- มีความกังวลว่าการเปลี่ยนกฎการตีความอาจชนกับ TypeScript loader ที่มีอยู่เดิม
- ผู้เขียน PR ตอบว่า PR นี้ไม่ได้ override กฎการตีความ และยังต้องระบุนามสกุลไฟล์อยู่
- มีความเห็นว่าสามารถรองรับรูปแบบ
import './file.ts' ได้ผ่าน allowImportingTsExtensions และแนวทางนี้ก็สอดคล้องกับ Deno
- หากต้องการรันไฟล์ซอร์สเดียวกันโดยตรงและให้ build tool สร้างผลลัพธ์ JavaScript ด้วย ก็อาจให้ build tool รับผิดชอบการเปลี่ยน
file.ts เป็น file.js
การ merge และงานต่อเนื่อง
- PR ถูก merge เข้า
nodejs:main เมื่อวันที่ 24 กรกฎาคม 2024
- ขนาดการเปลี่ยนแปลงคือ 8 commits, 89 files, เพิ่ม 2,190 บรรทัด และลบ 25 บรรทัด
- มีป้ายกำกับอย่าง
semver-minor, experimental, module, esm, notable-change
- มีการพูดคุยว่าควรกล่าวถึงฟีเจอร์นี้ในหน้าคู่มือ TypeScript ของเว็บไซต์หรือไม่ และมี PR สำหรับอัปเดตที่เกี่ยวข้องเชื่อมไว้ด้วย
- มีการอภิปรายเป็น issue ถัดไปเกี่ยวกับการใส่ เวอร์ชัน TypeScript ที่ Node binary ใช้สำหรับการลบ type ลงใน metadata ของการเผยแพร่
1 ความคิดเห็น
ความคิดเห็นใน Hacker News
การลบ type ของ TypeScript ทำไม่ได้หากไม่มีไวยากรณ์ของ TypeScript การลบ type ไม่ใช่งานระดับ token และไวยากรณ์ของ TypeScript ก็เปลี่ยนแปลงอยู่เรื่อย ๆ
ตัวอย่างเช่น
foo < bar & baz > ( x )ใน TypeScript 1.5 นั้นbar&bazไม่ใช่นิพจน์ type ที่ถูกต้อง จึงถูก parse เป็นเหมือน(foo (x))แต่หลังจากมีการเพิ่มตัวดำเนินการ intersection type แล้ว มันจะถูก parse เป็นfoo<(bar & baz)>(x)และถูกทำให้ไม่กำกวมเป็นfoo(x)หากต้องการใช้ฟีเจอร์ TypeScript ล่าสุดต่อไป ก็ต้อง compile เป็น JS หรือคอยอัปเดตเวอร์ชัน Node ให้ใหม่อยู่เสมอ ซึ่งอาจเป็นการประนีประนอมที่ทีมที่ชอบอยู่กับ Node LTS ยอมรับได้ยาก
แนวทางคือใส่เวอร์ชันเสถียรไว้ใน core แต่ถ้า TypeScript ออกฟีเจอร์ใหม่หรือ breaking changes หรือผู้ใช้ต้องการใช้ฟีเจอร์ทดลองใหม่ ก็ให้อัปเกรดแยกต่างหากจาก NPM
วิธีนี้จะทำให้ผู้ใช้ไม่ถูกล็อกไว้ ขณะเดียวกันก็ยังรองรับ TypeScript เวอร์ชันหนึ่ง ๆ ได้ตลอดอายุ 3 ปีของ Node.js release: https://github.com/nodejs/loaders/issues/217
การเปลี่ยนแปลงไวยากรณ์ครั้งใหญ่ล่าสุดน่าจะเป็น conditional types ใน 2.8 ซึ่งเป็นช่วงที่ไวยากรณ์คล้ายตัวดำเนินการสามทาง
ifถูกใส่เข้ามาในตำแหน่งของ type ถ้าต้องทำถึงขั้นตรวจ type ด้วย type model เปลี่ยนไปมากตั้งแต่ 2.x แต่ไวยากรณ์โดยรวมค่อนข้างเสถียร และนวัตกรรมส่วนใหญ่ของ TypeScript ก็อยู่ด้าน type model กับ type inferenceแม้ยังอยู่ใน Stage 1 ซึ่งเป็นระยะต้น ๆ แต่ก็มีความพยายามจะทำให้ไวยากรณ์ type ของ TypeScript ส่วนใหญ่เป็นมาตรฐานสำหรับจุดประสงค์การลบ type ไม่ใช่การตรวจ type: https://github.com/tc39/proposal-type-annotations
ทีมที่ไม่ค่อยสนใจ V8 หรือฟีเจอร์ Node ล่าสุดและอยู่กับ LTS ก็น่าจะมีโอกาสน้อยที่จะสนใจฟีเจอร์ TypeScript ล่าสุดเช่นกัน
หาก Node.js สามารถรันไฟล์ TypeScript ได้โดยตรง compiler ของ TypeScript ก็อาจถูกใช้เป็นเพียง type checker แทนการลบ type และแปลงเป็น JavaScript คล้ายกับใน Python ที่ type checker ตรวจ type แล้วปล่อยไว้ตามเดิม ส่วน interpreter จะเพิกเฉยต่อ type hint
ที่น่าสนใจคือ ใน Python มี type checker ยอดนิยมหลายตัวที่ใช้ไวยากรณ์ type hint เดียวกันแต่มี semantics ต่างกัน ขณะที่ใน JavaScript ดูเหมือน TypeScript จะกลายเป็น type checker ยอดนิยมเพียงตัวเดียวโดยพฤตินัย
เคยได้ยินด้วยว่าใน Python บางคนเขียน type ไว้ใน source โดยไม่ตรวจ type ใช้เหมือนไวยากรณ์คอมเมนต์ที่สะดวกกว่า หาก Node.js รองรับการเพิกเฉยต่อ type วิธีแบบนั้นก็จะเป็นไปได้ใน JavaScript เช่นกัน
โดยส่วนตัว ความไม่สะดวกที่สุดของการใช้ JSDoc คือไวยากรณ์ import แต่หลังจาก TypeScript 5.5 เปลี่ยนไป ตอนนี้ก็ไม่ใช่ปัญหาแล้ว
อย่างไรก็ตาม bundler บางตัวก็ใช้ compiler ไม่เป็นทางการอย่าง SWC ทำงานนี้อยู่แล้ว และ Node เองก็กำลังทดสอบ SWC สำหรับฟีเจอร์นี้ด้วย
type hint ไม่ใช่แค่คอมเมนต์ธรรมดา แต่ยังเป็น hint ให้ IDE แสดง autocomplete ที่ดีขึ้น เช่น ชื่อด้วย
คิดว่าสิ่งนี้ควรเป็นส่วนหนึ่งของ language specification
สงสัยว่าถ้าฟีเจอร์นี้ไม่ได้อยู่หลังแฟล็ก แต่กลายเป็นค่าเริ่มต้นแล้ว ระบบนิเวศ NPM จะตอบสนองอย่างไร ไม่รู้ว่าผู้มีส่วนร่วมจะยังคง build เวอร์ชัน CJS และ ESM ตอนเผยแพร่โมดูล NPM อยู่ไหม หรือจะแค่ใส่
engine: nodejs >= 25ในpackage.jsonแล้วข้ามขั้นตอน build ไปเลยส่วนตัวคิดว่าถ้าโมดูล NPM ที่มีซอร์ส TS เลิกแจกจ่าย
dist/.cjsก็น่าจะดีกว่า เพราะจะชัดเจนขึ้นว่าควรวาง debugger กับconsole.logไว้ตรงไหน จากมุมของผู้มีส่วนร่วมใน NPM สิ่งยั่วยวนให้ตัดขั้นตอน build ออกก็คงแรงมากเช่นกันแต่แค่ dependency ตัวเดียวแจกจ่ายไฟล์ TS สมมติฐานที่ว่า “ทุกคนรับไฟล์ TS” ก็อาจแพร่กระจายอย่างรวดเร็วได้ ทันทีที่ Node.js เอาสิ่งนี้ออกจากแฟล็กทดลองแบบ opt-in ทั้งคอมมูนิตี้ก็น่าจะเริ่มคาดหวังโดยนัยให้ผู้บริโภครองรับไฟล์ TS
ถ้าเป็นแบบนั้น ภายในไม่กี่เดือน Firefox กับ Safari ก็คงถูกกดดันให้ยอมรับด้วย และคอมไพเลอร์ JS ทั้งหมดก็จะไม่มีทางเลือกนอกจากทิ้ง annotation ของชนิดข้อมูลใน TS
ส่วนตัวแล้วแบบนี้ก็โอเคเหมือนกัน เพราะฝั่งที่ใช้ TS เองก็ใส่ขั้นตอนแปลงโค้ด TS เป็น JS และ
.d.tsลงในโมดูล NPM เพื่อรองรับผู้ใช้ JS ในจินตนาการบางกลุ่มอยู่แล้ว แต่ถ้า Node รับไฟล์.tsได้ ก็อาจลบขั้นตอนแปลงนั้นออกโดยไม่ทันสังเกต เลยสงสัยว่ามีกลไกอะไรที่จะป้องกันไม่ให้ผู้เผยแพร่ NPM เลิกแจกไฟล์js/d.tsแล้วไม่รู้ว่ามันพังเป็นแนวทางที่ให้อัปโหลดโค้ด TypeScript ได้โดยไม่ต้องมีขั้นตอน build และเมื่อ developer คนอื่นติดตั้ง ก็จะเห็นซอร์ส TypeScript ต้นฉบับ ไม่ใช่ JavaScript ที่ถูกแปลงแล้ว
.tsภายใน node_modules นี่เป็นหนึ่งในข้อจำกัดหลักเพื่อไม่ให้ระบบนิเวศพัง.cjsและ.mjsสำหรับ npm อยู่ และคงจะต้องแจกจ่ายทั้งสามเวอร์ชันถ้าเป็นโปรเจกต์ใหม่ที่เขียนจากศูนย์ ก็อาจแจกเฉพาะ TypeScript และไม่แปลงก็ได้
แก้ไข: ตามคอมเมนต์พี่น้องของ satanacchio ซึ่งดูเหมือนจะเป็นผู้เขียน PR และสมาชิกคณะกรรมการกำกับด้านเทคนิคของ Node.js การรองรับ TS มีไว้สำหรับรายการระดับบนสุด และไม่ใช้กับไลบรารีใน
node_modules.tsซึ่งเป็นซอร์สโค้ดของตัวเองลง npm แต่ทีม TypeScript คัดค้านเรื่องนี้อย่างมากเพราะปัญหาtsconfigและปัญหาประสิทธิภาพ ถึงอย่างนั้นก็ยังคาดหวังอยู่สักวันหนึ่ง Node อาจทำให้สามารถ สะท้อนข้อมูลชนิดขณะรันไทม์ จาก JS ได้
ถ้าเป็นแบบนั้นจะได้ประโยชน์มหาศาล ใน Python เพราะสามารถสะท้อนข้อมูลชนิดได้ เครื่องมือดี ๆ อย่าง pydantic จึงสร้างการตรวจสอบจากชนิดข้อมูลได้
ด้วยสัญกรณ์มาตรฐานเดียว ก็จะได้ทั้งการตรวจชนิด, การตรวจข้อมูลขณะรันไทม์, การสร้าง API และการสร้างเอกสาร API
ตอนนี้ใน JS เครื่องมืออย่าง Zod ต้องแทบจะประดิษฐ์สิ่งที่ TypeScript ทำอยู่แล้วขึ้นมาใหม่ เช่น
const mySchema = z.string();z.string()ของ Zod ไม่ได้ให้แค่ type safety แบบ TypeScript เท่านั้น TypeScript ให้การตรวจชนิดตอนคอมไพล์ ส่วน Zod เพิ่ม การตรวจสอบและการ parse ขณะรันไทม์z.string()ทำให้mySchemaกลายเป็น schema เชิงฟังก์ชันที่ parse และตรวจสอบได้mySchema.parse("some data")จะสำเร็จ ส่วนmySchema.parse(321)จะโยน exceptionเคยลองใช้ในจุดที่ต้องการการตรวจสอบขณะรันไทม์และการยืนยันภายในโปรเซส มันทำงานได้ค่อนข้างดี และยังดึง type ออกมาได้ด้วย เช่น
const A = z.string(); type A = z.infer; // stringกล่าวคือ ถ้ากำหนด type ใน Zod ก่อนแล้วอนุมาน type จากตรงนั้น ก็จะได้ทั้งการตรวจชนิดตอนคอมไพล์และขณะรันไทม์ เพียงแต่สำหรับ codebase เล็ก ๆ ที่เคลื่อนไหวเร็วอาจหนักเกินไป แต่ในสถานการณ์ที่ต้องตรวจสอบภายในโปรเซส มันค่อนข้างมีประโยชน์และภาระงานก็ไม่มาก
อย่างไรก็ตาม TypeScript อนุญาตให้ใช้ปลั๊กอินได้ แม้จะไม่ได้ถูกใช้กันมากนัก แต่สามารถเพิ่มฟีเจอร์อื่นเข้าไปในภาษาแล้วแปลงเป็น JavaScript ผลลัพธ์ได้
ปลั๊กอินที่เกี่ยวกับ runtime type มี Typia ซึ่งทำให้สามารถใช้ signature ของ TypeScript type ตอนรันไทม์ใน guard อย่าง
assert(myValue)ได้ มันจะดักจับการเรียกฟังก์ชันนี้ แล้วสร้างคำสั่งifแบบ exhaustive ใน JavaScript ที่ถูกแปลง เพื่อเช็กลักษณะของตัวแปรที่ส่งเข้าไปคงยังไม่น่าจะกลายเป็นส่วนหนึ่งของภาษาในอีก 4–6 ปีข้างหน้า แต่ก็มีไลบรารีที่ทำให้ทำเรื่องแบบนี้ได้อยู่แล้วในวันนี้
จริง ๆ แล้วต้องการ ระบบชนิดที่ sound แต่ TS ตั้งใจออกแบบมาให้ไม่ sound ต้องการระบบชนิดที่ไม่ยอมให้ทำแนวปฏิบัติการเขียนโค้ดแย่ ๆ แบบ TS และบังคับการออกแบบที่ทำให้โปรแกรมเร็วขึ้น ต้องการระบบชนิดแบบ Hindley-Milner
ถ้าอยากทำโมดูลให้เป็นโค้ดที่มี type ก็แค่เพิ่ม
"use type"อะไรทำนองนั้น โหมดนี้ควรห้ามส่วนแย่ ๆ อย่างการแปลงชนิดแบบบังคับ และป้องกันปัจจัยที่ทำให้ประสิทธิภาพเสีย เช่น การเปลี่ยนรูปทรง object หรือ type ของค่า หรือการสร้าง array ที่ผสมค่าอะไรก็ได้ข้อมูลที่เข้ามาจากโมดูลที่ไม่มี type จะถูกแปลง หรือถ้าแปลงไม่ได้ก็โยน error แล้วคอมไพเลอร์จะสามารถ optimize โค้ดที่มี type ได้ลึกขึ้นภายใต้การรับประกัน type ที่แข็งแรงกว่าและไม่มีความเสี่ยงต้องล้มเลิกกลางทาง
ValueErrorหรือ object เป็น instance ของSomeClassหรือเปล่า ผมยังเป็นมือใหม่ TS เลยคิดว่า JS ไม่มี type อื่นนอกจาก array, object, number, string และ Zod หรือฟังก์ชัน type guard ก็คืน object ทั่วไปในระดับ “เชื่อฉันเถอะ”ประสบการณ์นักพัฒนาของ Bun อยู่ในระดับที่ค่อนข้างไม่เคยมีมาก่อนในด้านนี้ และตอนนี้ use case ส่วนใหญ่ก็ครอบคลุมแล้ว หรือเมื่อเขียนสคริปต์รันด้วย
bun runBun ก็ไม่ crashในทางกลับกัน Node ไม่สามารถตั้งค่าให้ไม่ต้องระบุนามสกุลไฟล์ใน import ได้ และก็ไม่สามารถทำให้
tscเติมนามสกุล.jsให้ผลลัพธ์ที่คอมไพล์แล้วโดยอัตโนมัติได้ จึงต้องเพิ่ม bundler เข้ามาการรองรับ TypeScript แบบ native น่าจะช่วยแก้ความไม่สะดวกเล็ก ๆ นี้ได้พอสมควร แต่แม้จะเสถียรแล้ว ก็ยากจะจินตนาการว่าประสบการณ์ผู้ใช้หรือประสิทธิภาพจะทัดเทียม Bun ได้
ประสบการณ์นักพัฒนาและเครื่องมือก็อยู่ระดับยอดเยี่ยม Deno ตรวจ type ได้ด้วย และเท่าที่จำได้ก็ bundle TSC มาให้
Bun เป็นกระแสแรง แต่สำหรับงานจริงจัง ตอนนี้ Deno เป็นตัวเลือกที่ดีกว่าอย่างชัดเจน ถึงอย่างนั้น vision และการลงมือทำของ Bun ก็น่าประทับใจ และเป็นเรื่องดีสำหรับนักพัฒนา
bun installแล้วล้มเหลว เลยไม่เคยทำงานได้จริงสักครั้ง: https://github.com/search?q=repo%3Aoven-sh%2Fbun+bun+install...อยากได้ runtime สำหรับ TypeScript มานาน และก็ชอบ TypeScript มากจริง ๆ แต่ก็ตลกดีที่ออกจาก Java มานานแล้ว สุดท้ายกลับมาหาอะไรบางอย่างที่ใกล้ Java กว่ามาก
สุดท้ายสิ่งที่เราอยากได้คงเป็น Java ที่มี JIT, type system ที่สมบูรณ์กว่า และ gradual typing แม้ ecosystem ของ npm จะมีข้อเสียมากมาย แต่การใช้ library ใน ecosystem นี้รู้สึกกดดันน้อยกว่ามากและสนุกกว่า
น่าแปลกที่ Rust อยู่คนละปลายของสเปกตรัมภาษา แต่บางทีก็ให้ความรู้สึกคล้ายกัน
แก้ไข: คำว่า JIT ไม่เหมาะนัก ผมเขียนว่า JIT แบบขี้เกียจ แต่สิ่งที่ตั้งใจจะพูดคือความต่างของเวลาเริ่มต้นและ runtime เวลาเรียกใช้อะไรบางอย่างบน JVM กับ V8 Java ให้ความรู้สึกหนัก แต่ ecosystem ของ JavaScript ให้ความรู้สึกคล่องตัวกว่ามาก
และก็ไม่เข้าใจเลยว่า TypeScript ใกล้ Java มากกว่าตรงไหน สิ่งที่ทั้งสองมีร่วมกันมีแค่ชื่อที่ตั้งผิดว่า “Javascript” กับการรองรับ imperative programming เท่านั้น ที่เหลือมองว่าต่างกันมาก
แต่สิ่งที่ Java มีและคิดถึงใน TypeScript คือ runtime type reflection ecosystem ของ TypeScript มีวิธี workaround เรื่องนี้นับไม่ถ้วน แต่รู้สึกว่าทุกวิธีดูไม่ค่อยสวย
AoT ก็ใช้ได้ และถ้ามีตัวเลือกเป็น binary เดี่ยวได้ก็จะดี อุดมคติคือไม่มี runtime และสามารถตัดส่วนที่ไม่ใช้ได้อย่างชาญฉลาด ถ้ารันด้วย JIT ในเบราว์เซอร์ได้ด้วยก็ยิ่งดี
ยังอยากได้ความสะดวกจาก compiler และ type checker เช่น exhaustive pattern matching ด้วย
ฟีเจอร์ของ Deno ที่ผมชอบกำลังเข้ามาใน Node โดยตรง ดีมาก
ต่อไปอาจไม่ต้องติดตั้ง esbuild ตลอดเวลาเพื่อ strip type แล้วก็ได้ คาดหวังว่าจะเขียนสคริปต์ด้วย TypeScript ได้ง่ายขึ้นมาก
ช่วงหลังผมชอบใช้ Python สำหรับสคริปต์ใช้ครั้งเดียวมากกว่า แต่ในแง่ type ส่วนตัวคิดว่า TypeScript ดีกว่า Python โดยเฉพาะสคริปต์ใหญ่ ๆ ที่กลับมาดูอีกทีหลังผ่านไปหลายเดือน จะได้ประโยชน์จาก type มาก
ts-nodeด้วย แต่ส่วนตัวชอบtsxมากกว่าhttps://github.com/privatenumber/tsx
เป็นเดือนที่มีเรื่องเกิดขึ้นกับ Node เยอะจริง ๆ ก่อนอื่น v22.5.0 เพิ่ม node:sqlite เข้ามา และตอนนี้การรองรับ TypeScript ก็กำลังเข้ามาอีก ชอบทิศทางที่ Node กำลังไป
ผมเป็นผู้เขียน PR ถามอะไรก็ได้
ผมเริ่มใช้ Node.js ทำงานแบ็กเอนด์มานานแล้ว ซึ่งดูเหมือนจะมีข้อดีมากกว่าการเขียนโค้ดด้วย PHP หลายอย่าง และไม่ได้พ่วงปัญหาของ Java มามากนัก
แต่ Node ค่อนข้างหยาบ ๆ อยู่บ้าง และรู้สึกเหมือนเป็นภาษาที่ถ้าจะทำให้ได้ภาษาตามที่ต้องการก็ต้องเอาโน่นนี่มาต่อเติมเข้าไป สุดท้ายผมก็เริ่มใช้ Go ซึ่งใช้ง่ายกว่ามาก และแม้บางครั้งจะเยิ่นเย้อกว่ามาก แต่ความปลอดภัยของชนิดข้อมูลก็ทำให้การเขียนโค้ดง่ายขึ้น
TypeScript ดูเหมือนเป็นตัวเลือกที่ดี แต่สุดท้ายก็เป็นการต่อเติมอีกชั้นหนึ่งอยู่ดี ผมไม่ค่อยแน่ใจว่าเมื่อใช้ TypeScript แทน Go แล้วจะได้คุณค่าอะไรเพิ่มขึ้น การมีชนิดข้อมูลที่ชัดเจนนั้นดี แต่ก็ไม่ได้แก้ปัญหาอื่น ๆ ของภาษาที่ Go แก้ไปแล้ว Deno ก็แก้ได้บางส่วน
ข้อได้เปรียบใหญ่ของ Node เหนือ Go คือสามารถทำต้นแบบได้อย่างรวดเร็ว แต่พอใช้ TypeScript ดูเหมือนข้อได้เปรียบนั้นจะลดลงไปมาก ดังนั้นจึงยากจะตัดสินว่านี่เป็นความก้าวหน้าที่ดี หรือเป็นการทำให้ Node สูญเสียคุณสมบัติที่เคยทำให้มันเป็นตัวเลือกที่ดี
จากคำว่า “ต่อเติม” ปัญหาอาจไม่ใช่ตัวภาษาเอง แต่อาจเป็นการไม่มี เฟรมเวิร์กที่มีจุดยืนชัดเจน ซึ่งจัดการทุกอย่างให้เป็นค่าเริ่มต้นแบบ Django ก็ได้ ผมชอบใช้ Django แต่การออกนอกเส้นทางที่กำหนดไว้ก็ยากขึ้นเล็กน้อย
cdktfและดูเป็นตัวเลือกที่สมเหตุสมผลกว่า Go