[英]Typescript custom restriction with Generics
在開發庫時,我發現在使用 Generics 時對我來說看起來像一個錯誤:
type R<A> = A extends Bottom ? A : A
type Bottom = { test: number }
const f = <A extends Bottom>(a: A) => {
useIt(a) // type error here
}
const useIt = <A extends Bottom>(a: R<A>) => console.log(a)
正如您在Playground 示例中看到的那樣,由於某些不清楚的原因a
不能用作R<A>
,即使此類型等價於A
。
類型錯誤是:
Argument of type 'A' is not assignable to parameter of type 'R<A>'.
Type 'Bottom' is not assignable to type 'R<A>'.
使用具體類型而不是泛型將按預期工作,例如:
type X = {test: 1}
const x: R<X> = {test: 1} // all good
const noX: R<X> = {test: 2} // error
對於具體類型,具有更好的限制類型也將按預期工作:
type R<A> = A extends Bottom ? A : never
const x: R<X> = {test: 1} // all good
const error: R<{}> = {} // type error as expected given that {} doesn't extend Bottom
那么,有什么方法可以使它與 Generics 一起使用?
這更多的是設計限制而不是錯誤。 未解析的條件類型(依賴於尚未指定的泛型類型參數的類型)或多或少被編譯器完全延遲,幾乎沒有任何東西可以分配給它們。
有一個未解決的問題microsoft/TypeScript#23132建議使用泛型約束來確定對未解決的條件類型的可分配性; 我認為如果實施此建議,您的示例代碼將起作用(因為A extends Bottom
將被視為正確)...因此您可能想要 go 該問題並給出它並可能解釋您的用例如果您認為它更引人注目比那里的東西。
還有microsoft/TypeScript#33912 ,它建議使用控制流分析來確定對未解析條件類型的可分配性,如果要實現它也可能會有所幫助。
現在我認為“讓它工作”的唯一方法是使用type assertions ,如:
useIt(a as R<A>)
或表達您的類型,使其不再是未解決的條件類型,如果可能的話; 在您的示例代碼中, R<A>
是無條件A
,所以
// type R<A> = A extends Bottom ? A : A
type R<A> = A
會解決它。
實際上,我看到您將代碼的另一部分中的R<A>
更改為本質上是Extract<A, Bottom>
。 在某些情況下, Extract<T, U>
可以替換為交集T & U
而不會產生不良影響; 你可以試試:
// type R<A> = A extends Bottom ? A : never
type R<A> = A & Bottom
這也可能奏效。
好的,希望有幫助; 祝你好運!
經過大量修改后,我通過顯式添加限制解決了這個問題:
const f = <A extends Bottom>(a: R<A>) => {
useIt(a) // works
}
const useIt = <A extends Bottom>(a: R<A>) => console.log(a)
請注意,現在f
參數具有與useIt
相同的約束,這將使編譯器滿意。 事后看來,這實際上是有道理的,因此我們 100% 確定該類型也可用於useIt
:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.