การตรวจสอบประเภทคลาสใน TypeScript


240

ใน ActionScript เป็นไปได้ที่จะตรวจสอบประเภท ณ รันไทม์โดยใช้ตัวดำเนินการ is :

var mySprite:Sprite = new Sprite(); 
trace(mySprite is Sprite); // true 
trace(mySprite is DisplayObject);// true 
trace(mySprite is IEventDispatcher); // true

เป็นไปได้ไหมที่จะตรวจสอบว่าตัวแปร (ขยายหรือ) เป็นคลาสหรือส่วนต่อประสานกับ TypeScript หรือไม่?

ฉันไม่พบอะไรเกี่ยวกับเรื่องนี้ในสเป็คภาษา มันควรจะมีเมื่อทำงานกับคลาส / อินเตอร์เฟส

คำตอบ:


319

4.19.4 ตัวดำเนินการ instanceof

ตัวinstanceofดำเนินการต้องการให้ตัวถูกดำเนินการด้านซ้ายเป็นประเภทใด ๆ ชนิดวัตถุหรือชนิดพารามิเตอร์ชนิดและตัวถูกดำเนินการด้านขวาจะเป็นประเภทใด ๆ หรือชนิดย่อยของประเภทอินเทอร์เฟซ 'ฟังก์ชัน' ผลลัพธ์จะเป็นประเภทดั้งเดิมบูลีนเสมอ

ดังนั้นคุณสามารถใช้

mySprite instanceof Sprite;

โปรดทราบว่าตัวดำเนินการนี้อยู่ใน ActionScript ด้วย แต่ไม่ควรใช้ที่นั่นอีกต่อไป:

ตัวดำเนินการ is ซึ่งเป็นสิ่งใหม่สำหรับ ActionScript 3.0 ช่วยให้คุณทดสอบว่าตัวแปรหรือนิพจน์เป็นสมาชิกของชนิดข้อมูลที่กำหนดหรือไม่ ในเวอร์ชันก่อนหน้าของ ActionScript ผู้ดำเนินการ instanceof จัดเตรียมการทำงานนี้ แต่ใน ActionScript 3.0 ผู้ดำเนินการ instanceof ไม่ควรใช้เพื่อทดสอบการเป็นสมาชิกประเภทข้อมูล ตัวดำเนินการ is ควรใช้แทนตัวดำเนินการ instanceof สำหรับการตรวจสอบชนิดด้วยตนเองเนื่องจากนิพจน์ x instanceof y เพียงตรวจสอบสายโซ่ต้นแบบของ x สำหรับการมีอยู่ของ y (และใน ActionScript 3.0 ห่วงโซ่ต้นแบบไม่ได้ให้ภาพที่สมบูรณ์ของ ลำดับชั้นการสืบทอด)

TypeScript instanceofแบ่งปันปัญหาเดียวกัน เนื่องจากเป็นภาษาที่ยังอยู่ในระหว่างการพัฒนาขอแนะนำให้คุณระบุข้อเสนอของสิ่งอำนวยความสะดวกดังกล่าว

ดูสิ่งนี้ด้วย:


54

TypeScript มีวิธีการตรวจสอบประเภทของตัวแปรในรันไทม์ คุณสามารถเพิ่มฟังก์ชั่นการตรวจสอบที่ส่งกลับชนิดกริยา ดังนั้นคุณสามารถเรียกใช้ฟังก์ชันนี้ภายในคำสั่ง if และตรวจสอบให้แน่ใจว่ารหัสทั้งหมดในบล็อกนั้นปลอดภัยที่จะใช้ตามประเภทที่คุณคิด

ตัวอย่างจากเอกสาร TypeScript:

function isFish(pet: Fish | Bird): pet is Fish {
   return (<Fish>pet).swim !== undefined;
}

// Both calls to 'swim' and 'fly' are now okay.
if (isFish(pet)) {
  pet.swim();
}
else {
  pet.fly();
}

ดูเพิ่มเติมได้ที่: https://www.typescriptlang.org/docs/handbook/advanced-types.html


29
นี่ไม่ใช่การพิมพ์ตัวตรวจสอบรันไทม์ แต่เป็นเพียงการตรวจสอบว่าวัตถุมีคุณสมบัติที่แน่นอน นี่อาจเป็นสิ่งที่ดีสำหรับประเภทสหภาพดังนั้นจึงใช้ได้กับกรณีนี้โดยเฉพาะ แต่ไม่สามารถสร้าง "isThingy" สำหรับทุกสิ่งเช่นนี้ได้ นอกจากนี้หากทั้งปลาและนกสามารถว่ายน้ำได้ ฉันดีใจที่ฉันใช้ Haxe ซึ่งมีการตรวจสอบประเภทที่เชื่อถือได้คุณจึงสามารถใช้Std.is(pet, Fish)งานได้กับประเภทอินเตอร์เฟสและอื่น ๆ
Mark Knol

4
ฉันคิดว่าคำตอบนี้มีประโยชน์ แต่ฉันคิดว่าคุณสามารถปรับแต่งให้แม่นยำยิ่งขึ้น isFishตัวเองเป็นคำกริยาที่ถูกสร้างขึ้นและร่างกายของมันไม่ได้จำเป็นต้องเป็นกริยาหนึ่งซับ ข้อดีของการทำเช่นนี้คือคอมไพเลอร์เข้าใจเวลารวบรวมฟังก์ชั่นที่เป็นไปได้ที่เหมาะสม แต่โค้ดของคุณภายในisFishจะถูกเรียกใช้ในรันไทม์ คุณสามารถให้ยามมีinstanceofข้อความเช่นreturn pet instanceof Fish(สมมติว่ามันเป็นคลาสและไม่ใช่อินเตอร์เฟส) แต่สิ่งนี้จะไม่จำเป็นเนื่องจากคอมไพเลอร์เข้าใจinstanceofโดยตรง

4
สิ่งนี้เรียกอีกอย่างว่า "User Defined Type Guards" ดูที่basarat.gitbooks.io/typescript/content/docs/types/…
Julian

@ MarkKnol จริงๆแล้วมันคือการตรวจสอบรันไทม์ แต่นำมาซึ่ง typescript ความสามารถในการทำความเข้าใจประเภทอนุมานเช่นกัน (ความหมาย: คุณสามารถไว้วางใจฉันนี้จะเป็นประเภท X หรือ Y เพราะฉันจะทดสอบที่รันไทม์)
Flavien Volken

3
คุณอาจต้องการที่จะต้องพิจารณาใช้(pet as Fish)ตั้งแต่ tslinter (<Fish>pet)จะบ่นเกี่ยวกับ ดูtslint doc
ไบรอัน

1

คุณสามารถใช้instanceofโอเปอเรเตอร์สำหรับสิ่งนี้ จาก MDN:

ตัวดำเนินการอินสแตนซ์ของการทดสอบว่าคุณสมบัติต้นแบบของตัวสร้างปรากฏที่ใดก็ได้ในห่วงโซ่ต้นแบบของวัตถุ

ถ้าคุณไม่รู้ว่าต้นแบบและโซ่ต้นอะไรฉันขอแนะนำให้มองมัน นอกจากนี้ที่นี่เป็นตัวอย่างของ JS (TS ที่คล้ายกันในแง่นี้) ซึ่งอาจทำให้แนวคิดชัดเจนขึ้น:

    class Animal {
        name;
    
        constructor(name) {
            this.name = name;
        }
    }
    
    const animal = new Animal('fluffy');
    
    // true because Animal in on the prototype chain of animal
    console.log(animal instanceof Animal); // true
    // Proof that Animal is on the prototype chain
    console.log(Object.getPrototypeOf(animal) === Animal.prototype); // true
    
    // true because Object in on the prototype chain of animal
    console.log(animal instanceof Object); 
    // Proof that Object is on the prototype chain
    console.log(Object.getPrototypeOf(Animal.prototype) === Object.prototype); // true
    
    console.log(animal instanceof Function); // false, Function not on prototype chain
    
    

โซ่ต้นแบบในตัวอย่างนี้คือ:

สัตว์> สัตว์. ต้นแบบ> วัตถุ. สัตว์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.