【问题标题】:Static generic function to check keyof prototype of typeof...?用于检查 typeof 的 keyof 原型的静态泛型函数...?
【发布时间】:2019-09-29 22:20:39
【问题描述】:

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

由于它是一个静态函数,我无法在工厂类中定义新的返回类型。所以我试图依赖访问 ['prototype'] 就好像它是一个枚举。这是一个明智的方法吗?此外,似乎我需要扩展某些东西的 typeof 以使编译器能够访问“原型”属性。我想知道是否可以在保持导入函数静态的同时以更好的方式编写...?

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);
    }
}

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    我可能会这样做:

    // 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,您可以通过newable 类函数类型new()=&gt;T(或{new(): T})描述T-objects 的零参数类型。您可以将 T 保留为构造函数类型,但是要引用实例类型,您必须执行 T['prototype'](这很好)或使用 built-in 类型别名 InstanceType&lt;T&gt;(这可能会更好)...不过,这是更冗长乏味的代码。裸T 多次和一个new()=&gt;T 比一个裸TInstanceType&lt;T&gt; 多次更好。

    不太重要但仍然值得注意:

    • 我删除了 AU 类型,因为您在示例代码中没有对它们做任何事情。一般来说,未使用的泛型参数是bad idea,应该避免使用。

    • 我假设你想用untypedObject某事,对吧?我通过Object.assign() 将其属性合并到构造的typedObject 中。

    • 有一个built-in类型别名叫做Partial&lt;T&gt;,和{[K in keyof T]?: T[K]}是一样的,所以就用它了。

    • 一旦您将T 作为实例类型,您就不必将typedObject 注释为T 或断言new targetType()T。编译器将从typedObject 的已知类型推断为构造函数。

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

    【讨论】:

    • 哇 - 很好的答案!能够在构造函数中运行 new() 的绝妙技巧......我想知道这是否会导致任何类型的速度损失,而不是使用 ['prototype']? - 但很高兴知道两者都可以。一个问题是我在这里实际做的是调用类型 T 的静态函数......我没有包含在我的初始代码中。所以这并不能解决我的确切问题(因为现在我无法处理 T 类型),但它为我提供了如何干净地编写它的良好指导。标记它正确。谢谢!
    猜你喜欢
    • 2022-01-26
    • 2020-12-24
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    相关资源
    最近更新 更多