簡體   English   中英

Typescript:為什么我們不能為泛型類型分配默認值?

[英]Typescript: Why is it that we cannot assign default value to generic type?

以下面為例。 我不太確定錯誤消息的含義,但從邏輯上看,簽名是完全有效的。 這只是TS不支持嗎?

function _createNominalCollection<isOutputOrdered_T extends boolean>(
  input: nominal_T,
  processingFunc: (count: number) => number,
  orderedOutput: isOutputOrdered_T = true,
)

^^^
Type 'boolean' is not assignable to type 'isOutputOrdered_T'.
  'boolean' is assignable to the constraint of type 'isOutputOrdered_T', but 'isOutputOrdered_T' could be instantiated with a different subtype of constraint 'boolean'.ts(2322)

正如@VLAZ 指出的_createNominalCollection<false>()是有問題的。 讓我們再看看這個錯誤:

“布爾”可分配給“isOutputOrdered_T”類型的約束,但“isOutputOrdered_T”可以用約束“布爾”的不同子類型實例化。ts(2322)

這意味着您將顯式<false>類型作為通用參數傳遞, isOutputOrdered_T現在被限制為false但默認參數為true ,這將違反這一點。

或者換句話說, truefalseboolean的子類型,而您的 function 允許 boolean 被約束到這些子類型中的所有子類型,但不會保證所有子類型的分配。

讓我提出一個替代方案。


When you have a function that returns different types based on different arguments, you should always consider if function overloads are better suited to model that instead of generics. 它們允許您以簡單的方式將 map 參數模式專門用於特定的返回類型,而根本不需要任何 generics。

例如:

// sorted version
function myFn(orderedOutput?: true): 'sorted'

// unsorted version
function myFn(orderedOutput: false): 'unsorted'

// Implementation
function myFn(orderedOutput: boolean = true): 'sorted' | 'unsorted' {
  return orderedOutput ? 'sorted' : 'unsorted'
}

// Testing
const a = myFn(true) // sorted
const b = myFn(false) // unsorted
const c = myFn() // sorted

在這里,您為 function 創建兩個簽名。 第一個“排序”版本不接受任何參數或true 第二個“未排序”版本接受false 然后你有一個處理這兩種情況的實現。

操場

您收到此錯誤的原因是因為 isOutputOrdered_T 可能是 boolean 子類型,例如type truthy = truetype falsy = false ,而不是完整的 boolean,例如type bool = true | false type bool = true | false的。 例如:

function _createNominalCollection<T extends boolean>(
  orderedOutput: T
) {}

type booleanSubtype = true;

_createNominalCollection<booleanSubtype>(false);

在這個例子中,編譯器會抱怨傳遞 false,因為booleanSubtype只允許 true 作為輸入:

“false”類型的參數不能分配給“true”類型的參數

如果是真實的 boolean 子類型,就像在示例中一樣,您的默認值將不是有效輸入,這就是編譯器警告您的原因。 如果您像這樣鍵入默認值,則您的示例可以在沒有編譯器警告的情況下工作:

function _createNominalCollection<T extends boolean>(
  orderedOutput: T = false as T
) {}

但如前所示,這對於真實的子類型實際上並不正確,只是消除了錯誤。

您可以選擇不將默認值分配給 false - 將其保留為未定義。

function f<T extends boolean=false>(a?: T) {
   return a ? 'isTrue' : 'isNotTrue'
}

我想我會質疑為什么你首先需要這個通用的。 返回類型是否會根據此標志而改變? 如果它確實改變了為什么它需要是單個 function,那么擁有 2 個不同名稱的函數不是更有意義嗎?

您收到錯誤是因為您將true分配給orderedOutput作為默認參數。

如果您調用_createNominalCollection(..,..,false)約束類型參數isOutputOrdered_T將被推斷為false 當然,不允許將值true分配給false類型的參數。

暫無
暫無

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

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