我有以下類結構:
class App<objectList extends {}> {
private objects: Map<keyof objectList, any> = new Map();
add<T extends keyof objectList>(name: T, type: objectList[T]) {
this.objects.set(name, type);
this['get' name] = () => {
return type;
}
return this;
}
}
當我創建這個類的一個新實體時,我想向它添加額外的物件,稍后我想用getObjectType()實體上的函式進行檢索。
例子:
const App = new App<{Test: string, Test2: number}>().add('Test', 'this is my test string').add('Test2', 5);
App.getTest(); // returns 'this is my test string'
App.getTest2(); // returns 5
這按預期作業,但是打字稿抱怨這些功能不存在。是否有可能以某種方式強輸入類似的情況?
更新
是否有可能以某種方式add直接在構造函式中執行函式的功能?
class App<objectList extends {}> {
constructor(initObjects: objectList) {
/** iterate over the initObjects, create the functions **/
}
}
const inst = new App<{Test: string, Test2: number}>({
'Test': 'this is my test string',
'Test2': 5
});
inst.getTest();
uj5u.com熱心網友回復:
對于最初提出的問題:
編譯器并沒有真正跟蹤型別突變,所以我們必須告訴它我們在add();的主體內做什么。具體來說,我們需要手動表示我們想要處理回傳的型別this。這是一種方法:
add<K extends Extract<keyof O, string | number>>(name: K, type: O[K]) {
this.objects.set(name, type);
(this as any)['get' name] = () => {
return type;
}
return this as this & Record<`get${K}`, () => O[K]>
}
當您add使用 a nameof typeK和 a typeof type O[K](O您正在呼叫的位置objectsList)呼叫時,回傳值將是 type this & Record<`get${K}`, ()=>O[K]>。這是兩者的交集型別this以及具有單個屬性的物件,其鍵是`get${K}`(通過將字串與鍵連接得到的模板文字型別),其值是回傳型別值的無引數函式。我們必須使用型別斷言來說明回傳的值是這種增強型別,因為編譯器無法跟蹤這樣的事情。"get"KO[K]this
無論如何,您可以驗證它是否按需要作業:
const app = new App<{ Test: string, Test2: number }>().
add('Test', 'this is my test string').
add('Test2', 5);
app.getTest(); // no error
app.getTest2(); // no error
另一方面,如果您想跳過構建器模式,而是將整個型別的物件傳遞O給App建構式,那么您需要App類實體具有靜態未知的動態鍵;也就是說,App<O>具有依賴于 的鍵O。這是可以描述的,但不能直接用class或interface宣告。首先讓我們描述App建構式型別應該是什么樣子:
new <O>(initObjects: O) => App<O>
它應該有一個構造簽名,它接受一個initObjectstype 引數O,并回傳一個 type 值App<O>,它的定義如下:
type App<O> = {
[K in keyof O as `get${Extract<K, string | number>}`]:
() => O[K]
};
這是一個映射型別與重新映射鍵,以便為每個鍵K中O,App<O>具有相同名稱的關鍵與"get"前面加上它。并且該鍵處的屬性值是一個無引數函式,它從 回傳屬性型別的值O。
同樣,我們想說App建構式具有該形狀,但編譯器無法驗證它。所以我們需要使用另一種型別斷言(并且使用類運算式更容易避免使用虛擬類名):
const App = class App {
constructor(initObjects: any) {
Object.keys(initObjects).forEach(
k => (this as any)["get" k] = () => initObjects[k]
);
}
} as new <O>(initObjects: O) => App<O>;
看看內部App類的實作如何以適當的方式將 的每個成員復制initObjects到this。讓我們測驗一下:
const inst = new App({ Test: "this is my test string", Test2: 5 });
console.log(inst.getTest().toUpperCase());
看起來挺好的!
Playground 鏈接到代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/317163.html
標籤:打字稿
