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

typescript - การพิมพ์ฟังก์ชันที่ห่อทุกอาร์กิวเมนต์เป็นอาร์เรย์


ฉันกำลังพยายามพิมพ์ฟังก์ชันอย่างถูกต้องที่รับอาร์กิวเมนต์และห่อมันเป็นอาร์เรย์ อย่างไรก็ตาม ฉันไม่สามารถทำให้การพิมพ์ทำงานได้อย่างถูกต้อง

function wrapInArray<T>(data:T):T extends Array<infer K>? K[]: T[]{
  
  return Array.isArray(data)? [...data]:[data] 
  // ^ Type '(T & any[])[number][]' is not assignable to type 'T extends (infer K)[] ? K[] : T[]'
}

const a = wrapInArray('test') // string[]

const b = wrapInArray([1,2]) // number[]

ฟังก์ชันทำงานถูกต้อง และถ้าฉันลองใช้ฟังก์ชัน TypeScript จะสรุปประเภทการคืนค่าถูกต้อง ตอนนี้ฉันสงสัยว่าทำไมฉันถึงได้รับข้อผิดพลาดในประกาศฟังก์ชันเอง

สนามเด็กเล่น TS

คำตอบ #1

นี่เป็นเพราะลักษณะของฟังก์ชัน isArray ซึ่งถูกพิมพ์แบบนี้:

isArray(arg: any): arg is any[];

ดังนั้นเมื่อมันเป็นจริง arg is any[] หมายความว่าข้อมูลเป็น any[] แต่คุณก็ได้บอกว่ามันเป็น T ดังนั้นคุณจะได้ T & any[]...

แล้วถ้าเป็นแบบนี้ล่ะ (ไม่จำเป็นต้องมีการโอเวอร์โหลดและโบนัส เราไม่จำเป็นต้องระบุว่าฟังก์ชันส่งค่ากลับอะไร เราจะปล่อยให้ Typescript สรุปให้เราก็ได้):

function wrapInArray<T>(data: T | T[]){ //function wrapInArray<T>(data: T | T[]): T[]
  if (Array.isArray(data)) {
    // (parameter) data: T[]
    // T was either T | T[] but it's an array, we're left with only T[]
    return [...data]
  } else {
    // (parameter) data: T
    // data was either T | T[] but it's not an array so we're left with T
    return [data] // we return [T]
  }
}

const a = wrapInArray('test') // string[]

const b = wrapInArray([1,2]) // number[]

สนามเด็กเล่น TS

คำตอบ #2

คุณสามารถลองใช้การโอเวอร์โหลดฟังก์ชันได้:

function wrapInArray<T extends any[]>(data: T): T;
function wrapInArray<T>(data: T): T[];
function wrapInArray<T>(data: T):T | T[]{
  return Array.isArray(data)? [...data]:[data] 
}

const a = wrapInArray('test') // string[]

const b = wrapInArray([1,2]) // number[]

สนามเด็กเล่น TS

บทความที่เกี่ยวข้อง