首页 文章

在可以产生结果的对象上定义类型的Typescript

提问于
浏览
1

如果我有一个这样的对象

let obj = {
   property1:()=>{ return Date()} // eg it doesn't have to be a date
   property2:()=>{ return 1}   
}

现在我想将其转换为类型

{
   property1:Date,
   property2:number
}

我将如何在打字稿中定义这个 . 几乎所有我最终做的事情都做对了 .

我知道这些属性,所以我知道它就像

type Transform<T> = Record<keyof T,?>

我如何获得每个单独的属性进行转换,以便最终对象也可以输入 .

//有些人可能需要一些更实际的例子

让我们说这是一个反应应用程序 .

let dependencies = {user:UserContext}:{[key:string]:React.Context<any>}

现在我可以使用类似的东西将我的所有反应上下文转换为上下文中的实际实例

Object.entries(contextObject).map(([key,context])=>{
   return {[key]:useContext(context)}
}).reduce((a,b)=>{
  return {...a,...b}
},{})

这个对象将是所有被转换的属性 .

我接受了各种配置对象并转换属性,保持一切相同,

这可以是任何东西,将一些参数转换为db表,将依赖项转换为添加到类,而不必实际创建实例

这样做并不难,它输入它是为了在转换的另一端,我知道对象的类型已被转换成什么 .

1 回答

  • 3

    使用内置的 RecordReturnType 类型:

    /**
     * Apply the constraint of having functions as values.
     */
    type Source = Record<string, () => any>;
    
    /**
     * Map functions to their return types.
     */
    type Transform<T extends Source> = {
        [Property in keyof T]: ReturnType<T[Property]>
    }
    
    /**
     * Make sure the argument fulfills the requirement.
     */
    declare function transform<T extends Source>(source: T): Transform<T>;
    

    用法:

    let source = {
       property1: () => { return new Date() },
       property2: () => { return 1 }   
    }
    
    /**
     * `property1` is an instance of `Date`, property2 is a `number`.
     */
    const { property1, property2 } = transform(source);
    

    transform 函数可以这样实现:

    function transform<T extends Source>(source: T): Transform<T> {
        return Object
            .entries(source)
            .reduce(
              (cumulus, [key, value]) => Object.assign(cumulus, { [key]: value() }),
              Object.create({}),
            );
    }
    

相关问题