[英]Recursive Type Mapping in Typescript
我正在嘗試從包含本機類型驗證 function 的 object 中提取類型映射,例如,如果我有 object
const test = {
Test: {
Test1: {
Test2: SimpleStringValidator //return type is string or undefined but input can be anything
},
}
}
我想提取類型
type Extracted = {
Test: {
Test1: {
Test2: string
}
}
}
為此,我編寫了以下代碼來提取包含一組嵌套驗證函數的 object 的返回類型
樣本.ts
export type Validator<T> = NativeTypeValidator<T> | ObjectValidator<T>
export type NativeTypeValidator<T> = (n: any) => T | undefined
export type ObjectValidator<O> = {
[K in keyof O]: Validator<O[K]>
}
//native validators
export const SimpleStringValidator:NativeTypeValidator<string> = (val) => typeof(val) === "string" ? val : undefined
//object validator function
export const ObjValidator = <V>(validatorObj: ObjectValidator<V>) => (o:any):V =>{
let result = {} as V;
//we can only validate objects
if (typeof (o) !== "object") { return undefined; }
const validatorKeys = Object.keys(o) as [keyof ObjectValidator<V>]
validatorKeys.forEach((validatorKey) => {
const objValue = o[validatorKey] as V[keyof V];
const objectValidator = validatorObj[validatorKey]
if (!objectValidator) { return undefined } //do nothing if no validator exists for the key in o
//figure out if we have a nested object validator or a native validator at the corresponding key of validatorObj
if (typeof (objectValidator) === "object") {
result[validatorKey] = ObjValidator(objectValidator as ObjectValidator<V[keyof V]>)(objValue)
}
else {
const nativeValidator = objectValidator as NativeTypeValidator<V[keyof V]>;
result[validatorKey] = nativeValidator(objValue)
}
})
return result;
}
export const test = {
Test: {
Test1: {
Test2: SimpleStringValidator
},
}
}
export const validatorFunc = ObjValidator(test);
export const outputExample = validatorFunc({
Test: {
Test1: {
Test2: "hi"
},
}
})
outputExample.Test.Test1.Test2 = "1";
outputExample.Test.Test1.Test2 = 1; //vs code intellisense complains because needs to be type string
在我的情況下,智能感知自動完成嵌套屬性 Test2 並將類型作為字符串,但是當我創建類型聲明文件時,類型信息不同,我無法將此生成的類型正確導出到其他項目。 具體來說,它將屬性 Test1 的類型設置為 any。 我要生成的類型是驗證器函數的 output 和上面代碼中的 outputExample 類型。
生成的sample.d.ts
export declare type Validator<T> = NativeTypeValidator<T> | ObjectValidator<T>;
export declare type NativeTypeValidator<T> = (n: any) => T | undefined;
export declare type ObjectValidator<O> = {
[K in keyof O]: Validator<O[K]>;
};
export declare const SimpleStringValidator: NativeTypeValidator<string>;
export declare const ObjValidator: <V>(validatorObj: ObjectValidator<V>) => (o: any) => V;
export declare const test: {
Test: {
Test1: {
Test2: NativeTypeValidator<string>;
};
};
};
export declare const validatorFunc: (o: any) => {
Test: {
Test1: any;
};
};
export declare const outputExample: {
Test: {
Test1: any;
};
};
我需要使用根驗證器 object 作為提取類型的源,以尋找生成的聲明文件具有正確類型的解決方案。 我在 Typescript 操場上有這段代碼,它顯示了自動完成和放入 .d.ts 文件的內容之間的區別。
如果要提取:
{
Test: {
Test1: {
Test2: string
}
}
}
您可以使用這種遞歸類型映射,使用infer
:
type ValidatedObject<T> = Partial<{
[key in keyof T]: T[key] extends ObjectValidator<infer Type>
? ValidatedObject<Type>
: T[key] extends NativeTypeValidator<infer Type>
? Type
: T[key] extends object
? ValidatedObject<T[key]>
: T[key];
}>
注意:partial 的存在有兩個原因,一個是類型完全輸出到.d.ts文件中,另一個是
undefined
的返回值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.