Typescript类型任意数量的通用字段

时间:2018-07-12 14:51:13

标签: typescript

首先,我不确定自己想做的事是否可行,但我尝试100%地确定最好的方法。

interface Property<T> {
  value: T
}

interface PropertyBag {
  [key: string]: Property<???>
}

function toPlainObject(props: PropertyBag): ??? {
  return Object.keys(props)
    .reduce((acc, key) => Object.assign(acc, { [key]: props[key].value }), {})
}

一个示例说明我想做什么:

interface Person {
  name: string
  age: number
}

const name: Property<string> = { value: 'John Doe' }
const age: Property<number> = { value: 35 }

const props: PropertyBag = { name, age }

const person: Person = toPlainObject(props)

我想知道如何输入toPlainObjectPropertyBag的返回类型(类型是???)。使用TS甚至有可能吗?

1 个答案:

答案 0 :(得分:2)

如果您向PropertyBag添加一个额外的通用参数并改用映射类型,则可以做些接近的事情:

interface Property<T> {value: T }
type PropertyBag<T> = { [P in keyof T]: Property<T[P]> }

基本上T将作为财产袋的财产名称和财产类型的持有人。您可以像这样明确定义一个实例:

const name: Property<string> = { value: 'John Doe' }
const age: Property<number> = { value: 0 }
let bag : PropertyBag<{ name : string, age: number}> = { age, name };

interface Person { name : string, age: number}
let personBag : PropertyBag<Person > = { age, name };

您还可以创建一个有助于类型的函数,因此您不必手动指定所有属性和类型

function createBag<T>(props: PropertyBag<T>):PropertyBag<T> {
    return props;
}


const name: Property<string> = { value: 'John Doe' }
const age: Property<number> = { value: 0 }
let bag  = createBag({ age, name }); // infered as PropertyBag<{age: number;name: string;}>

您当然可以在函数中使用它:

function toPlainObject<T>(props: PropertyBag<T>): T {
    return (Object.keys(props) as Array<keyof T>)
        .reduce((acc, key) => Object.assign(acc, { [key]: props[key].value }), {}) as any;
}

const name: Property<string> = { value: 'John Doe' }
const age: Property<number> = { value: 0 }

const person:Person  = toPlainObject({ name, age })