簡體   English   中英

TypeScript映射類型推斷無法按預期工作

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

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