มีวิธี "แยก" ประเภทของคุณสมบัติอินเตอร์เฟส TypeScript หรือไม่?


124

สมมติว่ามีไฟล์พิมพ์สำหรับไลบรารี X ซึ่งมีอินเทอร์เฟซบางอย่าง

interface I1 {
    x: any;
}

interface I2 {
    y: {
        a: I1,
        b: I1,
        c: I1
    }
    z: any
}

ในการทำงานกับไลบรารีนี้ฉันต้องส่งผ่านวัตถุที่เป็นประเภทเดียวกันกับI2.y. แน่นอนฉันสามารถสร้างอินเทอร์เฟซที่เหมือนกันในไฟล์ต้นฉบับของฉัน:

interface MyInterface {
    a: I1,
    b: I1,
    c: I1
}

let myVar: MyInterface;

แต่แล้วฉันก็ได้รับภาระในการอัปเดตให้เป็นปัจจุบันจากไลบรารียิ่งไปกว่านั้นอาจมีขนาดใหญ่มากและส่งผลให้มีการทำซ้ำรหัสจำนวนมาก

ดังนั้นมีวิธีใดบ้างที่จะ "แยก" คุณสมบัติเฉพาะของอินเทอร์เฟซประเภทนี้ออกมา สิ่งที่คล้ายกับlet myVar: typeof I2.y(ซึ่งใช้ไม่ได้ผลและทำให้เกิดข้อผิดพลาด "ไม่พบชื่อ I2") ขอบคุณล่วงหน้า.


แก้ไข : หลังจากเล่นเล็กน้อยใน TS Playground ฉันสังเกตเห็นว่ารหัสต่อไปนี้บรรลุสิ่งที่ฉันต้องการ:

declare var x: I2;
let y: typeof x.y;

อย่างไรก็ตามต้องมีxการประกาศตัวแปรซ้ำซ้อน ฉันกำลังมองหาวิธีที่จะบรรลุสิ่งนี้โดยไม่ต้องประกาศนั้น


1
ซึ่งไม่ได้ผล - มันแสดงให้เห็นอย่างไร? ข้อความแสดงข้อผิดพลาดที่คุณเห็นคืออะไร?
Bartek Banachewicz

@BartekBanachewicz ปรับปรุง
Kuba Jagoda

คำตอบ:


251

มันเป็นไปไม่ได้ก่อน แต่โชคดีก็คือตอนนี้ตั้งแต่typescript รุ่น 2.1 มันได้รับการปล่อยตัวใน 7 ธันวาคม 2016 และแนะนำประเภทการเข้าถึงที่จัดทำดัชนีที่เรียกว่าประเภทการค้นหา

ไวยากรณ์ดูเหมือนการเข้าถึงองค์ประกอบ แต่เขียนแทนประเภท ดังนั้นในกรณีของคุณ:

interface I1 {
    x: any;
}

interface I2 {
    y: {
        a: I1,
        b: I1,
        c: I1
    }
    z: any
}

let myVar: I2['y'];  // indexed access type

ตอนนี้myVarมีประเภทของI2.y.

ตรวจสอบมันออกมาในtypescript สนามเด็กเล่น


1
ในกรณีที่ 'y' เป็นอาร์เรย์มีวิธีใดในการแยกประเภทขององค์ประกอบหรือไม่? เช่น I2 {y: {.. } []}
John B

1
@JohnB ใช่คุณสามารถทำได้ในลักษณะเดียวกันเพราะดัชนีอาร์เรย์ก็เหมือนกับคุณสมบัติของวัตถุ ตรวจสอบได้ที่นี่: typescriptlang.org/play/…
Kuba Jagoda

3
@JohnB ใช่คุณสามารถเข้าถึงได้ด้วยวิธีเดียวกันคือ I2['y'][0]ดู: typescriptlang.org/play/…
Michał Miszczyszyn

2
นี่คือความสามารถที่ยอดเยี่ยมจริงๆ
Geradlus_RU

1
สมมติว่าเรากำลังวนซ้ำคีย์ของวัตถุที่กำหนดโดยใช้I2เป็นประเภท ฉันจะรับประเภทของคีย์เฉพาะแบบไดนามิกได้อย่างไรเมื่อวนซ้ำ นี้; let z: typeof x[a];ซึ่งaเป็นที่สำคัญบางอย่างเป็นสตริงไม่ทำงาน มันบอกฉันว่าaหมายถึงค่าและต้องอ้างถึงประเภท ฉันจะทำสิ่งนี้ได้อย่างไร? มันเป็นไปได้ในทางใด? ขอบคุณ!
Emil Walser

-2

อินเทอร์เฟซเปรียบเสมือนนิยามของวัตถุ จากนั้น y เป็นคุณสมบัติของออบเจ็กต์ I2 ของคุณซึ่งเป็นประเภทหนึ่งในกรณีนั้นคือ "ไม่ระบุตัวตน"

คุณสามารถใช้อินเทอร์เฟซอื่นเพื่อกำหนด y แล้วใช้เป็นประเภท y ของคุณเช่นนี้

interface ytype {
   a: I1;
   b: I1;
   c: I1;
}

interface I2 {
    y: ytype;
    z: any;
}

คุณสามารถใส่อินเทอร์เฟซของคุณในไฟล์และใช้สารสกัดเพื่อนำเข้าในไฟล์อื่น ๆ ในโครงการของคุณ

export interface ytype {
   a: I1;
   b: I1;
   c: I1;
}



 export interface I2 {
        y: ytype;
        z: any;
    }

คุณสามารถนำเข้าด้วยวิธีนี้:

   import {I1, I2, ytype} from 'your_file'

ทุกอย่างเรียบร้อยดี แต่อย่างที่ฉันพูดถึงอินเทอร์เฟซ I1 และ I2 มาจากไลบรารีภายนอกและกำหนดไว้ในไฟล์ d.ts สำหรับไลบรารีนั้น ดังนั้นการมีอินเทอร์เฟซ ytype นี้จะเป็นการทำซ้ำรหัสและจะต้องมีการอัปเดตอย่างต่อเนื่อง
Kuba Jagoda
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.