[英]TypeScript type inference from array passed as function parameter
玩轉 TS 3.7.2 我發現了一個奇怪的邊緣情況,現在我很想知道更多關於函數中的類型推斷在這種特定情況下是如何工作的。
interface A {
functions: { t: number, a: { test: number }; };
}
interface B {
functions: { t: number, b: { ciao: number }; };
}
function combineStuff<TNamespace extends {}>(stuff: { functions: Partial<TNamespace> }[]): TNamespace {
// Implementation irrelevant for the question
return {functions: merge({}, ...stuff.map(s => s.functions))} as any;
}
const a: A = { functions: { t: 1, a: { test: 1 } } };
const b: B = {functions: { t: 1, b: { ciao: 2 } }};
const c = combineStuff([a, b]);
c.a.test;
c.b.ciao; // Error. Why is that?
const d = combineStuff<A['functions'] & B['functions']>([a, b]);
d.a.test;
d.b.ciao; // Works well
我的期望是cbciao
和dbciao
都是類型安全的,但是訪問cbciao
會導致錯誤。
從這個簡單的例子看來,泛型類型可以從數組的元素中自動推斷出來,這個假設也得到了以下事實的支持:在調用combineStuff<A['functions'] & B['functions']>([a, b]);
TS 編譯器驗證a
和b
的類型實際上是正確的。
此外,類型推斷適用於數組a
的第一個元素,我可以安全地訪問catest
。
為什么我需要顯式提供泛型類型給combineStuff()
以獲得正確的結果? 為什么對數組第一個元素的推斷工作正常?
問題在於,由於您在數組定義中使用Partial
,TS 將只選擇其中一種類型(它遇到的第一個類型),然后只檢查另一種類型是否可分配,因為我們正在談論Partial
所以它將會是。
解決方案是對整個對象使用類型參數。 這將捕獲A
和B
的聯合。 然后我們可以使用索引類型查詢( T['functions']
)來獲取function
類型的聯合。 並使用UnionToIntersection
jcalz將其轉換為所需的交叉點。
interface A {
functions: { t: number, a: { test: number }; };
}
interface B {
functions: { t: number, b: { ciao: number }; };
}
type UnionToIntersection<T> =
(T extends T ? (p: T) => void : never) extends (p: infer U) => void ? U : never;
function combineStuff<TNamespace extends Array<{ functions: object }>>(stuff: TNamespace): UnionToIntersection<TNamespace[number]['functions']>{
// Implementation irrelevant for the question
return null! as any;
}
const a: A = { functions: { t: 1, a: { test: 1 } } };
const b: B = { functions: { t: 1, b: { ciao: 2 } } };
const c = combineStuff([b, a]);
c.a.test;
c.b.ciao;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.