Typescript-如何使用接口创建符合不同结构的新对象

时间:2019-04-08 08:20:52

标签: typescript typescript-generics

我想使用接口的默认值创建一个对象,但是在 同时更改对象的结构。例如,对于此界面:

interface IPerson {
  name: string
  age: number
}

我想创建一个像这样的对象:

const person: IPerson = {
  name: {
    type: String,
    required: true
  },
  age: {
    type: Number,
    required: true
  }
}

我发现的唯一方法是将对象的类型添加到nameageIPerson界面,如下所示:

interface IPerson {
  name: string | IProp
  age: number | IProp
}

interface IProp {
  type: any
  required?: boolean
  // ...
}

我不想更改原始界面IPerson。所以我当时 想到这样的事情:

const person: IProperties<IPerson> = {
  // use properties of IPerson to determine which key/value pairs are valid in this object
}

2 个答案:

答案 0 :(得分:2)

您可以使用mapped type

interface IPerson {
  name: string
  age: number
}

type IProperties<T> = {
    [K in keyof T]: IProp
}

interface IProp {
  type: any
  required?: boolean
  // …
}

const person: IProperties<IPerson> = {
    // …
}

答案 1 :(得分:2)

您可以使用条件类型和映射类型来执行此操作。

interface IPerson {
name: string
age: number
ocupation?: string
}

type PropertyType<T> = 
    [T] extends [string] ? typeof String :
    [T] extends [number] ? typeof Number :
    [T] extends [Date] ? typeof Date :
    [T] extends [Function] ? typeof Function : // add any other types here
    new (...a:any[]) => T // default must be a constructor for whatever T is 

type IfRequired<T, K extends keyof T, IfYes, IfNo> =
    Pick<T, K> extends Required<Pick<T, K>> ? IfYes : IfNo

type PropertyDefinition<T> = {
    [P in keyof T]-?: {
        type: PropertyType<Exclude<T[P], null | undefined>> // will not work for unions!
        required: IfRequired<T, P, true, false>
    }
}

let personDefinition: PropertyDefinition<IPerson> ={
    age : {
        required: true,
        type: Number
    },
    name: {
        required: true,
        type: String,
    },
    ocupation: {
        required: false,
        type: String
    }
}