【问题标题】:TypeScript: Factor out function applied on all of Object's propertiesTypeScript:应用于所有对象属性的分解函数
【发布时间】:2020-12-24 08:25:58
【问题描述】:

假设我们有一些通用函数

function change<T>(something: T): IWhatever<T> {}

所以我可能有一个看起来像这样的对象

const stuff = {
    key1: change(1),
    key2: change('hello'),
    key3: change(false)
}

无论如何我可以制作一个看起来像这样的更简单的对象

const stuff = {
    key1: 1,
    key2: 'hello',
    key3: false
}

然后通过适当的 TypeScript 类型将更简单的对象传递给吐出第一个对象的函数?还假设更简单的对象可以随时更改属性,并且“某些功能”仍会产生适当的复杂对象。

我想不通,也不知道有没有可能。

【问题讨论】:

标签: typescript


【解决方案1】:

好吧,您可以使用Mapped Types 来实现这一点。您只需要使用 2 种类型映射即可:

  1. 剥离IWhatever&lt;T&gt;
  2. 将剥离操作应用于每个属性
//  a weird interface
interface IWhatever<T> {
  whut: T;
}

// a weird function that wraps everything into that weird interface
function change<T>(something: T): IWhatever<T> { return { whut: something }; }


// general type that defines all properties has to be type of IWhatever<T>
type Whatevered<R> = {
  [key in keyof R]: IWhatever<R[key]>
}

// this object suits the type of we defined above
const stuff = {
  key1: change(1),
  key2: change('hello'),
  key3: change(false)
}

// this map strips the IWhatever type
type UnWhateverify<T> = T extends IWhatever<infer R> ? R : T;

// this applies strping to all properties of the object
type Cleanser<T> = { [Key in keyof T]: UnWhateverify<T[Key]> }

// this function is a dummy(magic) function that illustrates the type action
function MagicJhonson<R, T extends Whatevered<R>>(item: T): Cleanser<T> {
  let cleansed = {} as any;
  // doing the cleaning here
  for (let key in item)
    cleansed[key] = item[key].whut; // that general type definition `Whatevered<R>` makes this valid  
  // you can also skip that and do some cast to any action here.

  return cleansed as Cleanser<T>;
}

const cleansedStuff = MagicJhonson(stuff);

console.log(cleansedStuff.key1) // number
console.log(cleansedStuff.key2) // string
console.log(cleansedStuff.key3) // boolean


// another dummy function to reverse apply the operation
function JhonsonMagic<T>(item: T): Whatevered<T> {
  let whuts = {} as any;
  for (let key in item) {
    whuts[key] = change(item[key])
  }

  return whuts as Whatevered<T>;
}

const oldStuff = JhonsonMagic(cleansedStuff);

console.log(oldStuff.key1) // whut :number
console.log(oldStuff.key2) // whut :string
console.log(oldStuff.key3) // whut :boolean

Playground Link

【讨论】:

  • 有了这个,我也可以反方向走吗?从清理后的对象开始,以 IWhatever'd 对象结束?
  • @ZeroSeventTen 你只需要一个返回Whatevered&lt;T&gt;的函数。查看更新的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 2016-04-25
  • 2018-10-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多