[英]TypeScript mapped types inference not working as expected
給定此功能:
export const combineValidators = <Input extends { [P in keyof Input]: (val: string) => Err }, Err>(
validators: Input
) => (values: { [P in keyof Input]?: unknown }): { [P in keyof Input]: Err } => {
// Ignore implementation.
return {} as { [P in keyof Input]: Err };
};
和這種用法:
const validator = combineValidators({
name: (val) => val ? undefined : 'error',
email: (val) => val ? undefined : 'error'
});
const errors = validator({
name: 'Lewis',
email: 'lewis@mercedes.com'
});
我希望TypeScript能夠將返回類型推斷為:
// Expected: `errors` to be inferred as:
interface Ret {
name: string | undefined;
email: string | undefined;
}
但是可以推斷為:
// Actual: `errors` inferred as:
interface Ret {
name: {};
email: {};
}
我已經在TypeScript運動場中創建了一個實時示例來演示該問題。
有人可以幫忙嗎?
不會以您期望的方式推斷出Err
。 使用ReturnType
條件類型從Input
提取返回類型可能更簡單:
type ReturnTypes<T extends Record<keyof T, (...a: any[]) => any>> = {
[P in keyof T]: ReturnType<T[P]>
}
export const combineValidators = <Input extends Record<keyof Input, (val: unknown) => any>>(
validators: Input
) => (values: Record<keyof Input, unknown>): ReturnTypes<Input> => {
return {} as ReturnTypes<Input>;
};
const validator = combineValidators({
name: (val) => val ? undefined : 'error',
email: (val) => val ? undefined : 'error'
});
const errors = validator({
name: 'Lewis',
email: 'lewis@mercedes.com'
});
我們甚至可以更進一步,如果您在驗證器函數中指定參數類型,則可以對傳遞給validator
的對象的字段進行類型檢查:
type ParamTypes<T extends Record<keyof T, (a: any) => any>> = {
[P in keyof T]: Parameters<T[P]>[0]
}
type ReturnTypes<T extends Record<keyof T, (...a: any[]) => any>> = {
[P in keyof T]: ReturnType<T[P]>
}
export const combineValidators = <Input extends Record<keyof Input, (val: unknown) => any>>(
validators: Input
) => (values: ParamTypes<Input>): ReturnTypes<Input> => {
return {} as ReturnTypes<Input>;
};
const validator = combineValidators({
name: (val: string) => val ? undefined : 'error',
email: (val) => val ? undefined : 'error', // if we leave it out, we still get unknown
age: (val: number) => val ? undefined : 'error'
});
const errors = validator({
name: 'Lewis',
email: 'lewis@mercedes.com',
age: 0
});
const errors2 = validator({
name: 'Lewis',
email: 'lewis@mercedes.com',
age: "0" // type error
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.