如何将Schema对象转换为等价TypeScript类型?编译器属性未识别问题
问题描述
能不能把下面的Schema对象:
const userSchema = { name: { type: String }, age: { type: Number }, };
转换成等价的TypeScript类型:
type userType = { name: string; age: number }
我试过基于Schema创建对象后用typeof获取类型,但编译器识别不了属性。以下是我的尝试代码:
type schemaType = { [key: string]: { type?: StringConstructor | DateConstructor | NumberConstructor; }; }; type resultType = { [key: string]: String | Date | Number; }; const createPropsFromSchema = (schema: schemaType) => { const result = { id: "" } as resultType; Object.keys(schema).forEach((key) => { if (schema[key].type == String) { result[key] = ""; } else if (schema[key].type == Date) { result[key] = new Date(); } else if (schema[key].type == Number) { result[key] = 0; } }); return result; }; const userSchema = { name: { type: String }, age: { type: Number }, }; const userProps = createPropsFromSchema(userSchema); console.log(userProps.name); //为什么编译器没有提示"name"?
解决方案
要实现这个需求,得让TypeScript保留Schema的键名和对应类型信息,用泛型+条件类型就能解决:
1. 定义类型映射工具
先创建一个类型,把构造函数类型转换成对应的TS基础类型:
type ConstructorToType<T> = T extends StringConstructor ? string : T extends NumberConstructor ? number : T extends DateConstructor ? Date : never;
再创建泛型类型,把Schema结构直接映射成目标类型:
type SchemaToType<S> = { [K in keyof S]: ConstructorToType<S[K]['type']>; } & { id: string }; // 对应你代码里默认的id字段
2. 改造工厂函数
把createPropsFromSchema改成泛型函数,让它能根据传入的Schema推断出返回值的具体类型:
const createPropsFromSchema = <S extends Record<string, { type: StringConstructor | NumberConstructor | DateConstructor }>>(schema: S) => { const result = { id: "" } as SchemaToType<S>; (Object.keys(schema) as Array<keyof S>).forEach((key) => { const field = schema[key]; if (field.type === String) { result[key] = "" as ConstructorToType<typeof field.type>; } else if (field.type === Date) { result[key] = new Date() as ConstructorToType<typeof field.type>; } else if (field.type === Number) { result[key] = 0 as ConstructorToType<typeof field.type>; } }); return result; };
3. 使用示例
现在再调用函数,编译器就能正确识别userProps的属性和类型了:
const userSchema = { name: { type: String }, age: { type: Number }, }; const userProps = createPropsFromSchema(userSchema); // 此时userProps的类型是 { id: string; name: string; age: number } console.log(userProps.name); // 编译器会提示name属性,类型为string
之前代码失效的原因
- 你定义的
schemaType是宽泛的索引签名{ [key: string]: ... },传入userSchema时,TypeScript会丢失具体键名(name、age)的信息,只知道这是个字符串键的对象。 resultType同样是宽泛的索引类型,所以返回的userProps在编译器看来只是{ [key: string]: String | Date | Number } & { id: string },没法确定具体有哪些属性。
内容的提问来源于stack exchange,提问作者Paulo Fernando
相关产品推荐
相关产品推荐

