打字稿地图对象返回类型

时间:2019-04-11 07:37:14

标签: reactjs typescript typescript-generics

我遇到了一些对我来说似乎很奇怪的行为。

在下面的示例中,我有两个函数,它们以一个对象作为输入并返回具有相同键但值不同的对象。使用useForm1时可以得到预期的结果。我可以访问输入对象的属性键,并且它也具有正确的值(Field)。

但是,当使用useForm2(使用Form<T>而不是内联的{ [P in keyof T]: Field }并乍看起来实际上是相同的)时,我也得到了一个具有键的对象不幸的是,值不是输入对象Field的类型,而是普通对象(又称{},没有任何属性。)。

任何人都可以解释为什么这两种方法产生不同的结果以及如何调整useForm2的定义吗?

type FormConfig<T> = {
  [P in keyof T]: {
    required?: boolean;
    validator?: (input: string) => void | Promise<void>;
    type: string;
  }
};

type Field = {
  required?: boolean;
  name: string;
  type: string;
  value: string;
};

type Form<T> = { [P in keyof T]: Field };

export const useForm1 = <T extends Object>(
  config: FormConfig<T>
): { [P in keyof T]: Field } => {
  // do some logic
};

export const useForm2 = <T extends Object>(config: FormConfig<T>): Form<T> => {
  // do some logic
};

const test1 = useForm1({
  login: {
    type: "text"
  }
});

const test2 = useForm2({
  login: {
    type: "text"
  }
});

1 个答案:

答案 0 :(得分:0)

Object是一种非常通用的类型,几乎不应在TypeScript中使用。在这种情况下,您希望将键值映射作为输入并返回经过处理的键-值映射,因此这是您应在所有约束中指定的类型:

type Form<T extends Record<string, any>> = { [P in keyof T]: Field };

export const useForm1 = <T extends Record<string, any>>(
  config: FormConfig<T>
): { [P in keyof T]: Field } => {
  // do some logic
  return null as any
};

export const useForm2 = <T extends Record<string, any>>(config: FormConfig<T>): Form<T> => {
  // do some logic
};

test2.login.required // works