[英]Make argument of a function required if a generic type is provided
我正在嘗試創建可用於嵌套 collections 的 class,因此我的函數具有 pathArgs,如您所見,它是可選的,這是因為對於 firebase 中的 collections 沒有嵌套,我不需要給出任何其他路徑。
但是,如果提供了PathIds
,我實際上需要這個。
class FirebaseService<T, PathIds = {}> {
public findOne(id: string, pathArgs?: PathIds): T { return {} as T };
}
type SomeEntity = {
hello: "hello"
}
所以如果我這樣做:
const firebase = new FirebaseService<SomeEntity>()
// this should be ok, actually pathArgs should NOT be possible to be given to it at all
firebase.findOne("someId");
// this should give me an error saying that the function does not accept a second argument
firebase.findOne("someId", { someRandomProp: "" });
但如果我這樣做:
const firebase = new FirebaseService<SomeEntity, { userId: string }>()
// this should now not be okay, and the function should require a second argument
// that is an object and matches { userId: string }
firebase.findOne("someId");
// and this should now be the only valid way to call this function
firebase.findOne("someId", { userId: "" });
唯一的區別是給 FirebaseService 的 generics
游樂場鏈接: TS Playground
編輯:
新游樂場鏈接: TS 游樂場
所以解決方案確實有效,但現在我收到一個錯誤:
Argument of type '[PathArgs<P>]' is not assignable to parameter of type 'PathArgs<P>'
在我使用這些函數的任何地方,它們現在都按預期工作,但這變成了一個內部錯誤。
一種方法是讓FirebaseService
的第二個類型參數P
控制方法的rest 參數的元組類型。 如果你用某種類型明確指定P
,那么 rest 元組應該看起來像[pathArgs: P]
; 否則,如果未指定,我們可以將其默認為 [the impossible never
type]( https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-never-type所以你的 class 看起來像) 然后 rest 元組應該看起來像[]
,空元組。
那是:
type PathArgs<T> = [T] extends [never] ? [] : [pathArgs: T];
declare class FirebaseService<T, P = never> {
public findOne(id: string, ...p: PathArgs<P>): T;
}
(我們檢查[T] extends [never]
而不是T extends never
的原因是因為后者將是分布式條件類型,因此會出現意外行為)。
讓我們測試一下:
const firebase1 = new FirebaseService<SomeEntity>()
firebase1.findOne("someId"); // okay
firebase1.findOne("someId", { someRandomProp: "" }); // error!
// Expected 1 arg, got 2 -> ~~~~~~~~~~~~~~~~~~~~~~
const firebase2 = new FirebaseService<SomeEntity, { userId: string }>()
firebase2.findOne("someId"); // error
// ~~~~~~~~~~~~~~~~~ <-- Expected 2 args, got 1
firebase2.findOne("someId", { userId: "" }); // okay
看起來不錯,第二個類型參數的存在導致需要第二個方法參數。 並且缺少第二個類型參數會導致第二個方法參數被禁止。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.