簡體   English   中英

如果提供了通用類型,則需要 function 的參數

[英]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.

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