網站搜尋

typescript - 如何在函數中對傳入的陣列類型進行類型縮小?


當處理陣列類型時,我想進行類型縮小,但聯合成員無法被區分。有趣的是,它們在第一個函數 print1()(沒有陣列)中能正常工作,但在第二個函數 print2() 中就不行。

type Point = {
  x: number;
  y:number;
}
type Pair = [number, number]

type Coords = Point | Pair

function print1(a: Coords): number{
  if("x" in a){
    return a.x;
  } else{
    return a[0];
  }
}

function print2(a: Pair[] | Point[]): void{
  if("x" in a[0]){
    console.log(a[0].x)
  } else{
    console.log(a[0][0])
  }
}

答案#1

有趣的是,它成功地縮小了 a[0],但沒有縮小 a[1] 或整個陣列,即使縮小 a[0] 也可以縮小整個陣列。如果還沒有人報告的話,你可以考慮報告這個問題。

在此之前,你可以用一個簡單的類型保護/謂詞來「修正」這個問題:

const isPairArray = (arr: Pair[] | Point[]): arr is Pair[] => arr[0] && 'x' in arr[0];

function print2(a: Pair[] | Point[]): void {
    if (isPairArray(a)) {
        console.log(a[0][0])
    } else {
        console.log(a[0].x)
    }
}

在那種情況下,a 已正確縮小為 Pair[] 或 Point[]。

答案#2

這是 TypeScript 的一個「限制」(實際上是 TypeScript 的一個很棒的特性,因為真正的問題出在 JavaScript)。根據 TypeScript,表達式 'x' in a[0] 中的 a[0] 可能與日誌語句 console.log(a[0].x) 中的 a[0] 引用的值不同。

在這種情況下,將 a[0] 存儲在一個變量中將解決這個問題。

function print2(a: Pair[] | Point[]): void{
  const b = a[0];
  if("x" in b){
    console.log(b.x)
  } else{
    console.log(b[0])
  }
}