我嘗試撰寫以下方法。
它開始變得非常復雜,因為現在每個接收結果的方法都catchUndefinedList必須能夠處理可變和不可變陣列。
有人可以幫我嗎?
/**
* Catch any errors with a list.
*/
export function catchUndefinedList<T> (list: readonly T[] | T[]): readonly T[] | T[] {
return nullOrUndefined(list) || !list?.length ? [] : list
}
編輯:添加 nullOrUndefined
export function nullOrUndefined (el: any): el is (undefined | null) {
return typeof el === 'undefined' || el === null
}
編輯:添加了一些簡單的示例來展示問題。
可以看出catchUndefinedList接收list1一個可變陣列作為引數。在這種情況下,即使list1是可變的,它也會輸出一個不可變的陣列,并且回傳的catchUndefinedList只是引數listwhenlist不是未定義的。
當嘗試推送list2它時,由于不變性而失敗并回傳 TS2339。
const list1 = ['foo']
const list2 = catchUndefinedList(list1)
list2.push('bar')
uj5u.com熱心網友回復:
首先,這個問題只有在 for 型別中允許null或被undefined允許時才真正有意義list。所以我假設你打算允許這樣做。
聽起來您希望函式的回傳值與輸入的陣列型別相同。這意味著您的函式需要在陣列上是通用的,而不僅僅是該陣列的成員型別。這是因為readonly陣列的-ness 是陣列型別的一部分,而不是成員。
這可能看起來像這樣:
export function catchUndefinedList<
T extends readonly unknown[]
> (list: T | null | undefined): T {
return (
nullOrUndefined(list) ||
!list?.length
? [] // Type 'T | never[]' is not assignable to type 'T'.
: list
)
}
// mutable
const list1 = ['foo']
const list2 = catchUndefinedList(list1)
list2.push('bar')
// immutable
const immlist1: readonly string[] = ['foo']
const immlist2 = catchUndefinedList(immlist1)
immlist2.push('bar') // Property 'push' does not exist on type 'readonly string[]'.(2339)
在這里可以看到,對可變陣列的推送是允許的,但對不可變陣列的推送是不允許的。這很好。
但是,這確實給元組帶來了問題。這就是我上面的代碼片段中出現這種型別錯誤的原因。想象一下你這樣呼叫這個函式:
const tuple2 = catchUndefinedList<[string, number, boolean]>(undefined)
tuple2[0].split('') // no type error, instead there is a runtime error
這是一個問題,因為您的函式[]在undefinedcase 中回傳,這不是此元組的有效型別。
您可以使用 a 使錯誤靜音,[] as unknown as T但這并不是真正推薦的。如果有人確實嘗試使用元組執行此操作,您可能會在奇怪的地方遇到運行時錯誤。
老實說,我不確定如何正確限制這一點,因為所有元組都是無界陣列的子型別。
支付地
也就是說,對于簡單的空檢查來說,這似乎相當復雜。你確定這是你要走的路嗎?
這段代碼所做的就是:
- 當
list為空或未定義時,它回傳一個新的零項陣列 - when
list是一個零項陣列,它回傳一個新的零項陣列 - 當
list是一個或多個專案的陣列時,它回傳list.
在我看來,這實際上與Nullish 合并運算子相同??
list ?? []
您的代碼與此行之間的唯一區別是,當list回傳零項而不是新的空陣列時。但它仍然是一個空陣列,所以這種區別可能并不重要。
但在上述所有情況下,這都是明智的:
// mutable
const list1 = ['foo'] as string[] | undefined
const list2 = list1 ?? []
list2.push('bar')
// immutable
const immlist1 = ['foo'] as readonly string[] | undefined
const immlist2 = immlist1 ?? []
immlist2.push('bar') // type error
// tuple
const tuple1 = ['a', 1] as [string, number] | undefined
const tuple2 = tuple1 ?? []
tuple2.push('c') // type error
操場
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/408809.html
標籤:
