Typescript嵌套类型映射

时间:2018-10-30 21:23:09

标签: typescript

我正在尝试处理打字稿中的模型验证。 我希望能够捕获验证定义的嵌套类型。

例如,我希望能够创建这样的验证器。

const validateUser = createValidator({
  name: {
    first: {
      value: "First"
    },
    last: {
      value: "Last"
    }
  },
  age: {
    value: 32
  },
  hasOnboarded: {
    value: false
  }
});

这将创建一个validateUser函数,该函数采用指定模型 类型并验证其类型。

我希望能够捕获类型,以便validateUser知道接受, 符合接口的对象。

type ValidateUser = typeof validateUser;

应输入

(
  model: {
    name: {
      first: string,
      last: string
    },
    age: number,
    hasOnboarded: boolean
  }
) => boolean

在TypeScript中可以吗?

1 个答案:

答案 0 :(得分:3)

使用2.8的功能,条件类型和infer关键字。

Playground

declare function createValidator<
  T extends {
    [key: string]: { value: any } | { [key: string]: { value: any } }
  }>(modelDescriptor: T): (validationSubject: {
    [key in keyof T]: T[key] extends { value: infer R }
    ? R
    : {
      [innerKey in keyof T[key]]: T[key][innerKey] extends { value: infer R } ? R : never
    }
  }) => boolean;

// const validateUser: (validationSubject: { name: { first: string; last: string; }; age: number; hasOnboarded: boolean; }) => boolean

const validateUser = createValidator({
  name: {
    first: {
      value: "First"
    },
    last: {
      value: "Last"
    }
  },
  age: {
    value: 32
  },
  hasOnboarded: {
    value: false
  }
});

让我们分解一下,因为这有点复杂。

首先,我们的函数接受类型参数T,其约束是它必须是一个对象,其中每个键都必须是{value: any}或嵌套对象,其中每个键都必须是{ {1}}。

我们的返回类型是一个对象,因此对于T中的每个键,我们都会检查该类型。如果它的类型为{value: any},则推断出{value: <whatever>}(并称其为<whatever>),则该键的值的类型为R(也就是{{1}下原始键的类型}键。

如果它不是R类型,那么根据我们最初的约束,它必须是value类型,因此返回类型成为对该内部对象的第二级映射,再次提取该类型嵌套对象{value: <whatever>}中的任何内容。

如果都不是(由于我们的限制,这是不可能的),则密钥的返回类型将为{[key: string]: {value: <whatever>}}。该部分永远都不能达到。