การใช้ type เป็นพารามิเตอร์ typescript

Sep 29 2020

วิธีใช้ type เป็นพารามิเตอร์ใน typescript

type myType = {}
const passingType = (t: Type) => {
    const x : t = {}
}

passingType(myType);

ฉันได้รับข้อผิดพลาด TS

't' refers to a value, but is being used as a type here. Did you mean 'typeof t'?

และ

'myType' only refers to a type, but is being used as a value here.ts(2693)

สำหรับการโทร

ความคิดใด ๆ ในการทำสิ่งนี้ให้สำเร็จ

คำตอบ

2 jcalz Sep 29 2020 at 14:44

นี้เป็นไปไม่ได้


ระบบประเภทคงที่ของ TypeScript (ซึ่งรวมถึงmyTypeคำจำกัดความและคำอธิบายประกอบประเภทของคุณ) จะถูกลบเมื่อโค้ดถูกปล่อยออกมาเป็น JavaScript JavaScript คือสิ่งที่รันรันไทม์ ที่รันไทม์ทั้งหมดที่คุณสามารถเข้าถึงมีค่า การลบประเภทหมายความว่ารหัสของคุณด้านบนจะกลายเป็นดังนี้:

const passingType = (t) => {
    const x = {};
};
passingType(myType);

มีค่าไม่มีชื่อเป็นส่งผ่านไปยังmyTypepassingType

และเนื่องจากประเภท typescript ไม่อยู่เป็นค่าที่รันไทม์ไม่มี "ประเภทของประเภท" Typeชอบสิ่งที่คุณกำลังโทร ดังนั้นแนวทางนี้จึงไม่สามารถทำได้โดยตรง


แทนที่จะคิดถึงการส่ง "type" ไปยังฟังก์ชันที่รันไทม์ซึ่งไม่เกิดผลดีที่สุดควรคิดเฉพาะเกี่ยวกับสิ่งที่คุณต้องการให้เกิดขึ้นที่รันไทม์ใน JavaScript บริสุทธิ์จากนั้นจึงเขียนประเภทเพื่อรองรับสิ่งนั้น

คุณต้องการทำอะไรกับ "type" ที่รันไทม์? คุณต้องการใช้เพื่อตรวจสอบว่าค่าเป็นประเภทนั้นหรือไม่? จากนั้นแทนที่จะส่งประเภทคุณอาจต้องการส่งผ่านในฟังก์ชัน type guard :

type Guard<T> = (x: any) => x is T;
const passingType = <T,>(t: Guard<T>) => {
    if (t(undefined)) {
        console.log("undefined IS of the guarded type T");
    }  else {
        console.log("undefined is NOT of the guarded type T");
    }
}

และคุณสามารถใช้มันได้ดังนี้:

function isUndefined(x: any): x is undefined {
    return typeof x === "undefined";
}

passingType(isUndefined); // undefined IS of the guarded type T

function isNumber(x: any): x is number {
    return typeof x === "number";
}
passingType(isNumber); // undefined IS NOT of the guarded type T

function isNumberOrUndefined(x: any): x is number | undefined {
    return isNumber(x) || isUndefined(x);
}

passingType(isNumberOrUndefined); // undefined IS of the guarded type T

กรณีการใช้งานจริงของคุณจะผลักดันข้อกำหนดสำหรับอาร์กิวเมนต์passingTypeควรมีลักษณะอย่างไร อาจเป็นโครงสร้างข้อมูลทั้งหมดที่แสดงถึงสิ่งต่างๆที่คุณต้องการทำด้วย "type" ในรันไทม์ ดังนั้นแม้ว่าตัวอย่างการ์ดประเภทนี้จะไม่ได้ผลสำหรับคุณ แต่ก็เป็นไปได้ว่าจะมีอย่างอื่น


แต่อีกครั้งคำตอบสั้น ๆ คือระบบประเภทสแตติกของ TypeScript ถูกลบดังนั้นจึงเป็นไปไม่ได้ที่จะอ้างถึงประเภทโดยตรงที่รันไทม์

ลิงก์สนามเด็กเล่นไปยังรหัส

1 CertainPerformance Sep 29 2020 at 14:43

ใช้ยาชื่อสามัญแทน อาร์กิวเมนต์ประเภทมีไวยากรณ์ที่แตกต่างจากอาร์กิวเมนต์ JS ที่ปล่อยออกมา ตัวอย่างเช่น:

type TheType = |
  { foo: string } |
  { bar: string };
const passingType = <T extends TheType>(obj: T) => {
    return { ...obj };
};

const result = passingType({ foo: 'foo' });

สิ่งนี้ส่งผลresultให้วัตถุใหม่ที่สร้างขึ้นภายในฟังก์ชันถูกพิมพ์อย่างถูกต้องเป็น{ foo: string }.