TypeScript:将一个接口转换为另一个

时间:2019-07-07 18:25:36

标签: typescript

想象我有两个界面:

interface A {
  foo: boolean,
  bar: string,
  baz: string
}

interface B {
  foo: number,
  bar: string,
  baz: string
}

现在我有一个实现接口A的对象,但是我需要将其传递给需要接口B的函数。我当然可以做:

const another_object: B = {
  foo: original_object.foo? 1 : 0,
  bar: original_object.bar,
  baz: original_object.baz
}

但是,如果A和B包含许多字段,则此表示法将很不方便。 在TypeScript中还有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

您可以使用传播运算符使此操作更简单:

contract

TypeScript可以使此操作更容易。准备好后,我将更新此答案。

更新: 上面的答案就足够了。 我想到的是一个覆盖范围更广的用例,该用例具有不兼容的类型,同时保留其余部分。

如果您要查找的是,可以在type-plus中检出const another_object: B = { ...original_object, foo: orignial_object.foo? 0: 1 } 函数。

类型有点复杂。 这是主要的逻辑:

typeOverrideIncompatible()

export type ANotB<A extends object, B extends object> = IsSame<A, B> extends true ? never : IsDisjoint<A, B> extends true ? A : { [k in Exclude<keyof A, keyof B> | KeysWithDiffType<A, B>]: A[k] } 来自集合论,表示ANotB中的属性,而不是A中的属性。

答案 1 :(得分:0)

  

我使用的数据库不接受布尔值,仅接受数字,但是在控制器逻辑中,我想对布尔值进行操作。

     

– dffsfs

如果这是唯一必要的转换,是的,可以使用反射来实现。

interface A {
  foo: boolean
  bar: string
  baz: string
}

interface B {
  foo: number
  bar: string
  baz: string
}

type U<T> = {
  [K in keyof T]: T[K] extends boolean ? number : T[K]
}

function toDbObject<T> (value: T): U<T> {
  return Object.entries(value).reduce<Partial<U<T>>>(
    (dbObject: Partial<U<T>>, [key, value]) => Object.assign(
      dbObject, { [key]: typeof value === 'boolean' ? +value : value }
    ),
    {}
  ) as U<T>
}

const a: A = {
  foo: true,
  bar: 'bar',
  baz: 'baz'
}

const b: B = toDbObject(a)

显然,U在这里不是一个好的名称,因此您应该使用一个更具描述性的名称,以适用于您的用例。

如果您的lib包含esnext,则可以使用Array.prototype.map()Object.fromEntries()代替Array.prototype.reduce()

function toDbObject<T> (value: T): U<T> {
  return Object.fromEntries(
    Object.entries(value).map(
      ([key, value]) => [key, typeof value === 'boolean' ? +value : value]
    )
  ) as U<T>
}