ค้นหาเว็บไซต์

typescript - ฉันจะป้องกันไม่ให้อ็อบเจ็กต์ถูกขยายได้อย่างไร?


เมื่อขยายคลาส การพิมพ์ประเภทของวัตถุในคลาสจะถูกทิ้งไปและฉันสามารถเพิ่มคุณสมบัติใดก็ได้ที่ต้องการ ฉันจะป้องกันสิ่งนี้ได้อย่างไร?

type StaticObject = {
  a: string[];
};

class System {
  staticObject?: StaticObject;
}

export default class ToggleInputSystem extends System {
  staticObject = { // Should be a type error but none appears
    a: ["hi"],
    added: true
  };
}

https://codesandbox.io/s/typescript-playground-export-ed1vx?file=/index.ts:0-254

คำตอบ #1

นี่เป็นเพราะลักษณะของการแก้ไขชนิดข้อมูลใน TypeScript เมื่อคุณกำหนดชนิดตัวแปร: สมมติให้เป็นตัวเลข (let a: number) มันสามารถบรรจุทุกชนิดย่อยของ number ได้ ซึ่งวิธีนี้ใช้ได้กับชนิดยูเนียน (let a: 1 | 2 | 3) เช่นเดียวกับอ็อบเจ็กต์ ดังนั้นชนิด {a: number, b: number} สามารถนำมาทำให้เป็นจริงกับอ็อบเจ็กต์ใด ๆ ก็ได้ ตราบใดที่มีคีย์ a และ b เป็น (ชนิดย่อยของ) number นอกจากนี้ โดยทั่วไปแล้วไม่จำเป็นต้องป้องกันการระบุชนิดเพิ่มเติม เนื่องจากฟังก์ชัน/คลาสทั้งหมดที่ทำงานกับอินเทอร์เฟซ (เช่น System) จะมีชนิดคุณสมบัติของ System ตามที่คาดหวัง พวกเขาไม่สนใจส่วนอื่น ๆ

โปรดทราบว่ามีข้อยกเว้นสำหรับกฎนี้ เมื่อคุณต้องการวัตถุเป็นพารามิเตอร์ของฟังก์ชันของคุณ และคุณประกาศมันแบบ inline (ในขณะเรียกใช้ฟังก์ชัน) typescript จะเกิดข้อผิดพลาด

function f(options: {duration: number, easing: string}) {}


f({duration: 200, somethingElse: "hi", easing: "ease"}) // Err

let optionsEnhanced = {duration: 200, somethingElse: "hi", easing: "ease"}
f(optionsEnhanced) // No Err

สิ่งนี้อาจดูสับสนในตอนแรก แต่จริงๆ แล้วเป็นเพียงการเตือนคุณว่าตัวเลือกที่ประกาศแบบอินไลน์มีคุณสมบัติที่จะไม่ถูกใช้เลย (เพราะไม่มีการอ้างอิงถึงมันที่ไหนเลยนอกจากภายในฟังก์ชัน)