[英]Typescript complex type inference
我想為 Rule3 做一個更詳細的類型推斷
export interface BaseOption {
required?:true;
}
export type Validator = {
[key in string]?: (
val: number,
formData: string,
callback,
props
) => void | Promise<void | Error>;
};
export interface RequiredFunc {
required: (message: string) => void;
}
export type CombineOptions<ExtraOption extends Validator> = ExtraOption &
RequiredFunc;
function Rule<ExtraOption extends Validator>(
options: ExtraOption | BaseOption
) {
return {} as ExtraOption extends BaseOption
? CombineOptions<ExtraOption>
: ExtraOption;
}
// Condition1
const rule1 = Rule({
a() {},
});
rule1.a; // There are code hints in vscode
// Condition2
const rule2 = Rule({ required: true });
rule2.required; // There are code hints in vscode
// Condition3
const rule3 = Rule({
a(f, b) {},
required: true,
});
rule3.required; // There are code hints in vscode
rule3.a; // There are no code hints in vscode
如何獲得條件 3 的代碼提示。如果我不手動添加 generics,則條件 3 在 vscode 中不起作用。 我的類型推斷是錯誤的方式嗎?
一般來說,如果您希望編譯器推斷類型參數X
,您應該給它一個X
類型的值來推斷它。 在您的Rule
function 中,您試圖從 X 類型的options
值推斷X extends Validator
X | BaseOption
X | BaseOption
,結果不是很好。 一旦options
可分配給BaseOption
,編譯器就放棄了更具體地推斷X
並退回到Validator
,導致rule2
和rule3
的類型為CombineOptions<Validator>
,這是正確的,但不足以滿足您的需求。
如果我們重構使得X
本身是一個擴展Validator | BaseOption
的類型 Validator | BaseOption
並且options
是X
類型,那么推理將正常工作並且編譯器不會忘記options
的特定屬性:
function Rule<X extends Validator | BaseOption>(options: X): RuleOutput<X> {
return {} as any // impl
}
現在的問題是弄清楚如何將 output 類型RuleOutput<X>
表示為輸入類型X
的 function 。 通過閱讀您的RequiredFunc
和CombineOptions
類型,看起來您想要做的是 output X
或多或少原樣,除非有一個名為required
的鍵,您希望將該屬性類型更改為(message: string) => void
。 這可以通過帶有條件類型的映射類型來表示,以檢查需要密鑰的required
:
type RuleOutput<X> = {
[K in keyof X]:
K extends "required" ? (message: string) => void : X[K]
}
讓我們看看它是否有效:
// Condition1
const rule1 = Rule({
a() { },
});
/* const rule1: {
a: () => void;
} */
// Condition2
const rule2 = Rule({ required: true });
/* const rule2: {
required: (message: string) => void;
} */
// Condition3
const rule3 = Rule({
a(f, b) { },
required: true,
});
/* const rule3: {
a: (f: number, b: string) => void;
required: (message: string) => void;
} */
看起來不錯。 您的rule1
與之前的類型相同,現在rule2
和rule3
更具體,並且知道作為options
傳入的特定鍵。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.