[英]Typescript - Class instance which implements generic type
我有一個使用通用接口創建類的函數。 實例的屬性由該泛型的參數設置,如下所示:
const ClassFactory = <T>() => {
class MyClass {
constructor(data: T) {
for (const key in data) {
if (!data.hasOwnProperty(key)) { continue; }
(this as any)[key] = data[key];
}
}
// other methods can be here
}
return MyClass;
}
const GeneratedClass = ClassFactory<{ id: number }>();
const myInstance = new GeneratedClass({ id: 1 });
console.log((myInstance as any).id); // logs 1
這按預期運行,但是有兩個問題
myInstance
沒有 T 的鍵 - 我希望myInstance.id
是一個數字this as any
以通過給定數據分配值為了解決第一個問題,我嘗試了從其他帖子中看到的各種方法,包括class MyClass implements T
,但它們都導致相同的錯誤: A class can only implement an object type or intersection of object types with statically known members.ts(2422)
。 我明白為什么會發生這種情況,但是因為在定義類時T
是已知的,有沒有辦法讓它起作用?
如果我在public data: T
屬性中有public data: T
,則正確鍵入myInstance.data.id
。 所以我的問題是,這可以通過跳過.data
部分來完成嗎?
提前致謝
受喬納斯·威爾姆斯 (Jonas Wilms) 評論的啟發,即使該類具有方法/靜態,我也可以通過返回來使其工作
return MyClass as (new (data: T) => T & InstanceType<typeof MyClass>) & typeof MyClass;
像這樣,以下所有內容都按預期輸入和運行
const myInstance = new GeneratedClass({ id: 1 });
console.log(myInstance.id, GeneratedClass.someStatic(), myInstance.someMethod());
但是,如果在類方法中使用new MyClass()
,這將無法正常工作。
它工作的一種解決方法是創建一個靜態的,它返回一個具有正確類型的實例
// inside the class
public static build(data: T): T & InstanceType<typeof MyClass> {
return new MyClass(data) as T & InstanceType<typeof MyClass>;
}
那么以下是預期的
const myInstance = GeneratedClass.build({ id: 1 });
console.log(myInstance.id, GeneratedClass.someStatic(), myInstance.someMethod());
完整的工作示例
const ClassFactory = <T>() => {
class MyClass {
constructor(data: T) {
for (const key in data) {
if (!data.hasOwnProperty(key)) { continue; }
(this as any)[key] = data[key];
}
}
public static build(data: T): T & InstanceType<typeof MyClass> {
return new MyClass(data) as T & InstanceType<typeof MyClass>;
}
public static someStatic() {
return 2;
}
public someMethod() {
return 3;
}
}
return MyClass as (new (data: T) => T & InstanceType<typeof MyClass>) & typeof MyClass;
}
const GeneratedClass = ClassFactory<{ id: number }>();
const myInstance = new GeneratedClass({ id: 1 });
console.log(myInstance.id, GeneratedClass.someStatic(), myInstance.someMethod());
const myBuiltInstance = GeneratedClass.build({ id: 1 });
console.log(myBuiltInstance.id, GeneratedClass.someStatic(), myBuiltInstance.someMethod());
我剛剛遇到了這個問題,並且能夠通過簡單地放棄new
並創建一個通用靜態方法Class.create()
來非常優雅地解決它,我在其中實例化並轉換為正確的類型。
interface MyGenericInterface<T = any> {
getTheThing(): T
}
class MyClass implements MyGenericInterface {
// Make constructor private to enforce contract
private constructor(private thing: any) {}
public getTheThing(): any {
return this.thing
}
static create<TypeOfThing = any>(thing: TypeOfThing) {
return new MyClass(thing) as MyGenericInterface<TypeOfThing>
}
}
const stringyInstanceWrong = new MyClass('thing') // Error
const stringyInstance = MyClass.create('thing')
const stringThing: string = stringyInstance.getTheThing()
const numberyInstance = MyClass.create(123)
const numberyThingWrong: string = numberyInstance.getTheThing() // Error
const numberyThing: number = numberyInstance.getTheThing() // Works!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.