我正在尝试从包含本机类型验证功能的对象中提取类型映射,例如,如果我有该对象
const test = {
Test: {
Test1: {
Test2: SimpleStringValidator //return type is string or undefined but input can be anything
},
}
}
我要提取类型
type Extracted = {
Test: {
Test1: {
Test2: string
}
}
}
为此,我编写了以下代码以提取包含一组嵌套验证函数的对象的返回类型
Sample.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
在我的情况下,intellisense自动完成嵌套属性Test2并将其类型设置为字符串,但是当我创建类型声明文件时,类型信息不同,因此无法将此生成的类型正确导出到其他项目。具体来说,它将属性Test1的类型设置为任何。我要生成的类型是上面代码中的validateatorFunc的输出和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;
};
};
我需要使用根验证器对象作为提取类型的源,以寻找生成的声明文件具有正确类型的解决方案。我在Typescript操场上放了这段代码,它显示了自动完成功能与.d.ts文件中内容之间的区别。
答案 0 :(得分:1)
如果要提取:
{
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];
}>
注意:部分存在是有两个原因,一个是类型完全输出到 .d.ts 文件,另一个是
>undefined
返回值。