背景
我有一個帶有 2 個型別引數的介面。第二個引數是可選的,默認為void。我還有一個實用程式型別 ( CommandReturnType),它使用條件型別來防止void在未提供第二個型別引數時成為回傳型別。
interface Command<IOType, AdditionalOutputType = void> {
execute(input: IOType): CommandReturnType<IOType, AdditionalOutputType>;
}
type CommandReturnType<A, B> = B extends void ? A : A | B;
我創建了一個實用程式型別,用于infer回傳包含 2 種型別引數型別的元組。
type GetCommandParamTypes<T extends Command<unknown, unknown>> =
T extends Command<infer IO, infer A> ?
[IO, A] :
never;
如果我為它提供只有一個型別引數的介面,它會按預期作業 - 它正確地void作為第二個引數回傳。
type type1 = GetCommandParamTypes<Command<string>>; // [string, void]
但是如果我為它提供一個類,該類實作了只有一個型別引數的介面,它會在兩個插槽中回傳一個具有該型別的元組。
class TypeACommand implements Command<string> {
execute(input: string): string {
return input;
}
}
type type2 = GetCommandParamTypes<TypeACommand>; // [string, string]
嘗試的解決方案
與我打算在 SO 上發布的大多數問題一樣,當我寫出問題時,它有助于澄清實際發生的情況。
我(認為我)現在明白execute在檢查類時檢索函式的輸入型別和回傳型別。所以我想到我可以用來Exclude<>從第二種型別中洗掉任何重復項。
type GetCommandParamTypes<T extends Command<unknown, unknown>> =
T extends Command<infer IO, infer A> ?
[IO, Exclude<A, IO>] :
never;
當為第二個型別引數提供型別時,效果很好:
class MixedTypeCommand implements Command<string | number, Function> {
execute(input: string | number): string | number | Function {
// do something with input here...
return something;
}
}
type type3 = GetCommandParamTypes<MixedTypeCommand>; // [string | number, Function] instead of [string | number, string | number | Function]
但是當它的型別引數匹配時Exclude<type type>回傳never。
type type4 = GetCommandParamTypes<TypeACommand>; // [string, never]
所以我想出了一個不那么狡猾的計劃,只是never用void. 哪個失敗了。
type ReplaceNever<T> = T extends never ? void : T;
type GetCommandParamTypes<T extends Command<unknown, unknown>> =
T extends Command<infer IO, infer A> ?
[IO, ReplaceNever<Exclude<A, IO>>] :
never;
type type5 = GetCommandParamTypes<TypeACommand>; // [string, never]
題
有沒有簡單的替換方法never?
如果沒有,是否有另一種解決方案可以讓我從第二個元組槽中洗掉重復型別,如果結果沒有,請將其替換為void?
所以:
type wrong = GetCommandParamTypes<TypeACommand>; // [string, string]
會成為:
type right = GetCommandParamTypes<TypeACommand>; // [string, void]
uj5u.com熱心網友回復:
我在這個SO 答案中找到了解決方案
條件型別分布在裸型別引數上。這意味著條件型別應用于聯合的每個成員。never 被視為空聯合。所以條件型別永遠不會被應用(因為聯合中沒有成員可以應用它)導致 never 型別。
簡單的解決方案是使用元組禁用條件型別的分配行為:
所以簡單地改變
type ReplaceNever<T> = T extends never ? void : T;
到
type ReplaceNever<T> = [T] extends [never] ? void : T;
解決了我的問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/350005.html
下一篇:為什么實作Hibernate@OneToMany關系會出現此錯誤?“物體映射中的重復列:XXX.Address列:id”
