網站搜尋

typescript - setter 中的 Proxy 屬性從未有過類型(附 MRE)


使用 TypeScript 4.5.4(目前最新版本),以下代碼(見下方或在 TypeScript playground 中)對於版本 1、2、3、4 會拋出錯誤 Type 'any' is not assignable to type 'never'.(2322),但對於版本 5 和 6 則不報錯。如果我們移除其中一個 num 屬性或 str 屬性,所有錯誤都會消失。

這個設計有解釋嗎?

const myObj = {
  num: -1,
  arr: [1, 2, 3],
  str: '',
};

const proxy = new Proxy(myObj, {
  set(target, prop: keyof typeof myObj, value) {
    /* none of these works */
    // Ver. 1
    if (prop in target) target[prop] = value;
    // Ver. 2
    target[prop] = value;
    // Ver. 3
    target[prop as keyof typeof myObj] = value;
    // Ver. 4
    switch (prop) {
      case 'num':
      case 'str':
        target[prop] = value;
        break;
    }

    /* while these works */
    // Ver. 5
    switch (prop) {
      case 'num':
        target[prop] = value;
        break;
      case 'str':
        target[prop] = value;
        break;
    }
    // Ver. 6
    switch (prop) {
      case 'num':
        target[prop] = value;
        break;
      default:
        target[prop] = value;
        break;
    }

    return true;
  },
});

console.log('proxy : ', proxy);

答案#1

摘要

在 TS 中,寫作會產生類型交集。

詳細

這是來自官方倉庫 microsoft/TypeScript#47295 的回答副本,這是一個「按預期工作」的功能。

在你大多數的設置中,prop 的類型並沒有從 "num" | "str" | "arr" 中縮小;因為你是 寫入 到 target[prop] 而不是從中讀取,這會產生一個所有可能類型的交集(而不是聯集)。如果沒有重疊,這個交集就會崩潰為 never,因為沒有一個可能的值適用於所有類型。

這個答案是為了結束這個問題而創建的。