[英]Typescript generic “cast” function
我想編寫一個函數,使我可以將所有對象屬性(我只有純對象)轉換為特定類型。 目前,我只想將基本類型轉換為boolean
, string
和number
。 遵循以下原則:
function castMembers<TObject extends object, TValue extends boolean | string | number>(instance: TObject, type: TValue): Record<keyof TObject, TValue> {
Object.keys(instance).reduce((result, k) => {
// ERROR
result[k] = new type(instance[k]).valueOf();
return result;
}, {});
}
將來,只要滿足我的接口定義(該接口定義必須包含valueOf
函數),我就可以將其類型擴展為任何類型。 所以...
我很清楚,我不能真正基於泛型類型實例化新對象,因為它們僅用於編譯時。 這就是為什么我添加了第二個參數,以便可以提供用於鑄造的構造函數的原因。 但是我遇到錯誤,或者我無效地編寫了TValue
通用參數或第二個參數的類型。
怎么寫這樣的功能?
我嘗試引入一個構造函數接口,這使我非常接近,但是仍然出現錯誤:
interface IConstructor<TValue> {
new(value?: any): TValue;
}
function castMembers<TObject extends object, TValue extends number | string | boolean>(instance: TObject, toType: IConstructor<TValue>): Record<keyof TObject, TValue> | never {
return (Object.keys(instance) as (keyof TObject)[]).reduce((result, key) => {
result[key] = new toType(instance[key]).valueOf() as TValue;
return result;
}, {} as Record<keyof TObject, TValue>);
}
實際上,我在玩游戲時自己解決了它。 我終於做到了。
這是代碼。
interface IPrimitiveLike<T> {
valueOf(): T;
}
interface IConstructor<T> {
readonly prototype: IPrimitiveLike<T>;
new(value?: any): IPrimitiveLike<T>;
}
export default function castMembers<TObject extends object, TValue extends IPrimitiveLike<unknown>>(instance: TObject, toType: IConstructor<TValue>): Record<keyof TObject, TValue> | never {
return (Object.keys(instance) as (keyof TObject)[]).reduce((result, key) => {
result[key] = new toType(instance[key]).valueOf() as TValue;
return result;
}, {} as Record<keyof TObject, TValue>);
}
此代碼將正確執行以下操作:
let obj = {
text: 'test',
value: 123,
negative: 0,
bool: true
};
castMembers(obj, Boolean); // { text: true, value: true, negative: false, bool: true }
castMembers(obj, String); // { text: 'test', value: '123', negative: '0', bool: 'true' }
castMembers(obj, Custom); // also works if your custom class defines a valueOf() function
我不確定的唯一一件事就是使用unknown
類型。 當然可以用any
代替它,但是理想情況下,它應該是與valueOf
返回類型相關的原始類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.