簡體   English   中英

當成員之一存在時,具有可選成員的通用映射類型約束不約束

[英]Generic mapped type constraint with optional member doesnt constraint when one of the member exist

const abc = <T extends object, P extends { [key in keyof T]?: number }>(
  a: T,
  b: P
) => {
  console.log(a, b);
};

const A = { x: "1", y: "2", z: "3" };
const b = { x: 1, y: 2, z: 3 };
const b1 = { x: 1, y: 2 };
const b3 = { m: 5 };
const b4 = { m: 5, x: 1 };

abc(A, b);
abc(A, b1);
abc(A, b3); // Type '{ m: number; }' has no properties in common with type '{ x?: number | undefined; y?: number | undefined; z?: number | undefined; }'
abc(A, b4); // expect type error just like b3 but it is not

由於m上不存在Ab4應該像b3一樣出錯,對嗎? 但為什么它不是錯誤以及如何解決它?

這是沙盒代碼和框

鍵入'{ m:數字; }' 與類型 '{ x?: number | 沒有共同的屬性。 不明確的; y?: 數字 | 不明確的; z?: 數字 | 不明確的; }。

認為它很清楚,b4 沒有錯誤,因為有 x?, y? 之一 z? 包括。 那是因為您從 T 擴展,而 T 來自您傳遞的第一個參數是 A。

原來這根本不是關於 generics 的,這應該是代表我的問題的更好方法:

const abc = <T extends { [index: string]: string }>(
  a: T,
  b: { [key in keyof T]?: number }
) => {
  console.log(a, b);
};

const A = { x: "1", y: "2", z: "3" };
const b4 = { m: 5, x: 1 };

abc(A, b4); // no error, not "expected"
abc(A, { m: 5, x: 1 }); // exact same value as b4 but throw error as "expected"

解決方案是您需要傳遞一個新值(不是變量的值)

有關解釋和其他解決方案(幫助類型),請閱讀此答案及其評論

更新,我找到了完美的解決方案:

const abc = <
  T extends { [index: string]: string },
  U extends { [key in keyof T]?: number }
>(
  a: T,
  b: keyof U extends keyof T ? U : never
) => {
  console.log(a, b);
};

const A = { x: "1", y: "2", z: "3" };
const b4 = { x: 1, y: 2, z: 3 };
const b5 = { m: 2, x: 5 };
const b6 = { x: 1, y: 2, z: 3, m: 2 };
const b7 = { x: 1 };

abc(A, b4); // no error, excat member
abc(A, b5); // error, excess member
abc(A, b6); // error, excess member
abc(A, b7); // no error, one of the member exist
abc(A, {}); // no error, since it is optional

// all work as expected

這部作品無論價值是否新鮮

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM