静态通用函数来检查typeof ...的原型的keyof

时间:2019-05-12 23:03:36

标签: typescript typescript-generics

有更好的方法吗?我正在尝试编写一个带有两个参数的静态工厂函数:一个通用对象和一个类类型,并返回给定类类型的新实例(或部分实例)。我要检查的是通用对象的属性是否不违反类的公共属性的类型或名称。

由于这是一个静态函数,因此无法在工厂类中定义新的返回类型。因此,我试图依赖于访问['prototype'],就好像它是一个枚举一样。这是明智的方法吗?似乎我还需要扩展某种类型,以便编译器可以访问'prototype'属性。我想知道是否可以在保持导入功能静态的同时以更好的方式编写代码??

export class emptyClass {
    //intentionally empty. Can we get rid of this somehow? If so, what would T extend?
}
export class Person {
    public id:number; 
    public name:string;
}

export class ImportObject<A> {
    public static ImportCastStatic<U,T extends typeof emptyClass>( 
            untypedObject:{[K in keyof T['prototype']]?:T['prototype'][K]}, 
            targetType:T)
            :T['prototype'] {
        let typedObject:T['prototype'] = <T['prototype']>new targetType();
        return (typedObject);
    }
}

export class Main {
    constructor() {
    //This is how I want to call it.
        let q = ImportObject.ImportCastStatic({name:"Alice",id:3}, Person);
    }
}

1 个答案:

答案 0 :(得分:2)

这是我可能要解决的方法:

// removing unused generic A from ImportObject<A>
export class ImportObject {
    // removing unused generic U from ImportCastStatic<U, T>
    // reinterpret T to be the instance type, not the constructor type
    public static ImportCastStatic<T>(
        untypedObject: Partial<T>, // Partial of T
        targetType: new () => T) // zero-arg constructor of T objects 
        : T {
        let typedObject = new targetType(); // no annotation/assertion required
        return Object.assign(typedObject, untypedObject); // do something with untypedObject
    }
}

这里重要的一点是,我将您的T更改为引用 instance 类型而不是 constructor 类型。在给定T的情况下,您可以通过T类似函数的类型new(或{{1},来描述new()=>T对象的零参数构造函数的类型。 }})。您可以将{new(): T}保留为构造函数类型,但是要引用实例类型,则必须要做T(可以)或使用built-in类型别名{{ 1}}(可能会更好)...不过,这是更加冗长乏味的代码。多次裸露T['prototype']和一次单独InstanceType<T>胜过多次裸露Tnew()=>T

不太重要但仍值得注意:

  • 我删除了TInstanceType<T>类型,因为您在示例代码中没有对它们进行任何操作。通常,未使用的通用参数是bad idea,应避免使用。

  • 我假设您想对A做某事,对吧?我通过Object.assign()将其属性合并到构造的U中。

  • 有一个名为untypedObject的{​​{3}}类型的别名,它与typedObject相同,所以就用它。

  • 一旦您将Partial<T>作为实例类型,则不必将{[K in keyof T]?: T[K]}注释为T或断言typedObject是{{1} }。编译器将从已知类型的T推断出它是构造函数。

好的,希望能有所帮助;祝你好运!