การยืนยันประเภทแบบอินไลน์ที่ทำงานเหมือนฟังก์ชันยืนยันใน Typescript?
ฉันรู้ว่าฟังก์ชันการยืนยัน (assertion functions) คืออะไร และเกี่ยวกับรูปแบบการยืนยันชนิดแบบ inline อื่น ๆ ฉันมีคำถามที่เกี่ยวข้องสองข้อ 1. ทำไมมันถึงไม่ทำงานเหมือนกัน (ให้ระดับการยืนยันเดียวกันกับ TypeScript) และ 2. เป็นไปได้ไหมที่จะได้ผลเหมือนกับฟังก์ชันยืนยันแบบ inline (เช่น มีรูปแบบการยืนยันแบบ inline อื่นที่ฉันพลาดไปหรือไม่)?
ตัวอย่าง: ฉันกำลังทำการตรวจสอบขณะรันด้วย typia แบบนี้:
import typia from "typia";
interface Point {
x: number;
y: number;
tag?: string;
}
function x(v: unknown) {
assertPoint(v);
console.log(v.x + v.y);
}
function assertPoint(v: unknown): asserts v is Point {
typia.assertEquals<Point>(v); // https://typia.io/docs/validators/assert/#assertequals-function
}
ข้างต้นทำงานได้ดี TypeScript ยอมรับว่า v เป็น Point หลังจากฟังก์ชัน assertPoint แต่จะ ไม่ ถ้าฉันใช้รูปแบบการกำหนดชนิดเหล่านี้:
...
v = <Point> typia.assertEquals<Point>(v);
v = typia.assertEquals<Point>(v) as Point;
ทำไมถึงเป็นแบบนั้น? พวกมันไม่ใช่แค่การยืนยันชนิดข้อมูลทั้งคู่เหรอ? และมีรูปแบบการยืนยันชนิดข้อมูลแบบในบรรทัดที่ทำงานเหมือนฟังก์ชันยืนยันที่ฉันสามารถใช้เพื่อหลีกเลี่ยงการต้องเขียนฟังก์ชันสำหรับทุกชนิดข้อมูลที่ฉันต้องการยืนยันในเวลารันไทม์หรือไม่?
คำตอบ #1
ฟังก์ชันการยืนยัน (assertion function) แคบลงของอาร์กิวเมนต์ของมันราวกับผ่านการวิเคราะห์การไหลของการควบคุม คำว่า "assertion" ที่นี่กล่าวถึงความหมายใน runtime ของการยืนยัน ซึ่งหมายความว่าเราสามารถสมมติได้ว่าถ้าการไหลของการควบคุมดำเนินต่อไปหลังจากการยืนยัน ข้อเท็จจริงที่ถูกยืนยันนั้นเป็นจริง (เพราะถ้าไม่ใช่จะเกิดข้อยกเว้นในเวลารันไทม์)
นี่ไม่เหมือนกับการระบุชนิด ซึ่งจะทำงานเฉพาะกับนิพจน์และไม่มีผลต่อสิ่งใดนอกเหนือจากนิพจน์นั้น
ปัจจุบันยังไม่มีวิธีการใช้การยืนยันประเภทแบบอินไลน์ล้วนที่ส่งผลต่อการวิเคราะห์การควบคุม มีคำขอฟีเจอร์มายาวนานที่ microsoft/TypeScript#10421 สำหรับเรื่องนี้ แต่ก็ไม่ได้เป็นส่วนโดยตรงของภาษา
และมันอาจเป็นไปได้น้อยมากที่สิ่งนี้จะเกิดขึ้นจริง เนื่องจาก ฟังก์ชันยืนยันโดยพื้นฐานแล้วมีวัตถุประสงค์นี้ แน่นอนว่ามีปัญหาที่คุณจะต้องเรียกใช้ฟังก์ชันที่ไม่ทำงานใด ๆ ในเวลารันไทม์ ซึ่งอาจเป็นข้อเสีย แต่คาดว่าไม่ใช่สิ่งที่มีลำดับความสำคัญสูงในการพัฒนาภาษา; ดูความเห็นนี้ใน microsoft/TypeScript#32695 คำร้องขอ pull ที่ได้นำฟังก์ชันยืนยันไปใช้:
มันคงจะดีแน่ถ้าสามารถระบุชนิดของการไหลของการควบคุมสำหรับตัวแปรได้โดยตรง แทนที่จะต้องแปลงชนิดในแต่ละครั้งที่อ้างอิง คุณสามารถได้ผลลัพธ์แบบเดียวกันด้วยการเรียกใช้ฟังก์ชัน
assertsแต่แน่นอนว่าการเรียกนั้นจะถูกใส่ลงในโค้ดที่ถูกสร้างขึ้น อย่างไรก็ตาม เครื่องเสมือน JavaScript ค่อนข้างเก่งในการลดต้นทุนของการเรียกฟังก์ชันว่าง
ดังนั้นในตอนนี้ดูเหมือนว่าตัวเลือกของคุณคือ: ทำการยืนยันชนิดที่ทุกการอ้างอิงถึงตัวแปรที่คุณต้องการยืนยันชนิด ซึ่งเป็นการซ้ำซ้อนแต่จะมองไม่เห็นในเวลารันไทม์; หรือสร้างโค้ด JavaScript บางอย่างที่ไม่ได้ทำอะไรเป็นประโยชน์ในเวลารันไทม์ แต่ทำให้ประสบการณ์การใช้ TypeScript ของคุณง่ายขึ้น (ฟังก์ชันยืนยันชนิด, คัดลอกตัวแปรที่ยืนยันชนิดไปยังตัวแปรใหม่ ฯลฯ)