将”Convert Schema to a Type”翻译为中文:将模式转换为类型。

huangapple go评论52阅读模式
英文:

Convert Schema to a Type

问题

以下是代码的中文翻译:

我想要将此模式对象转换为其等效的类型是否可能

type userType = {
  name: string;
  age: number
}

我的方法是基于模式创建一个对象然后使用 typeof 获取类型但编译器无法识别 props 😞

当前尝试

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"?

希望这有助于您理解代码中的内容。

英文:

I would like to convert this schema object:

const userSchema = {
  name: { type: String },
  age: { type: Number },
};

To it's equivalent type, is it possible?

type userType = {
  name: string;
  age: number
}

My approach was to create an object based on the schema, and then use typeof to get a type, but the compiler doesn't recognize the props 😢

Current attempt:

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); //why the compiler didn't suggest "name"?

答案1

得分: 1

问题并不是非常琐碎,但根据您所需的功能数量、属性可以有多少种不同类型等等,它可以简化一些。通常情况下,如果需要更多功能,解决方案可以相对容易地扩展。

我不知道,为什么要使用字符串、数字等构造函数,而不仅仅使用字符串来表示类型,比如 'string'、'number'。这不太重要,但可以简化事情。

如果我们最初假设对象只包含字符串、数字和日期构造函数,我们可以首先创建一个类型,该类型接受其中之一并返回相应的类型。

type PropertyType = [
  StringConstructor,
  NumberConstructor,
  DateConstructor
][number];

type ConstructorType<T extends PropertyType> = T extends StringConstructor
  ? string
  : T extends NumberConstructor
  ? number
  : T extends DateConstructor
  ? Date
  : never;

PropertyType 只是定义了属性的允许类型。然后 ConstructorType 是一个类型,用于检查传递的类型是否是其中之一,并返回相应的类型。

如果使用字符串而不是构造函数,这可以只是一个类型,如下所示:

type PrimitiveTypeMap = {
  string: string;
  number: number;
  boolean: boolean;
  // ...等等
};

可以轻松添加任何基本类型,但这不是重点。

然后,您需要一个接受对象的类型,再次我们假设对象是具有字符串键和类型为 { type: PropertyType } 的值的记录类型。

type InferObjectSchema<T extends Record<string, { type: PropertyType }>> = {
  [K in keyof T]: ConstructorType<T[K]["type"]>;
};

这只是创建了一个映射类型,将先前定义的类型应用于对象中的每个值。

这是一个示例链接:链接

英文:

The problem is not super trivial, but depending on the amount of functionality you need, how many different types etc can the properties be.. etc, can they be objects or other collection, it can be simplified a bit. And generally the solution can be extended fairly easily if more functionality is needed.

I don't know, is there a reason why to use string, number..etc constructors rather than just a string to represent the type like 'string', 'number'. Does not matter too much but can simplify things.

If we assume initially that the object will contain only string, number and date constructor we can first create a type that takes one of these and returns the corresponding type.

type PropertyType = [
  StringConstructor,
  NumberConstructor,
  DateConstructor
][number];

type ConstructorType&lt;T extends PropertyType&gt; = T extends StringConstructor
  ? string
  : T extends NumberConstructor
  ? number
  : T extends DateConstructor
  ? Date
  : never;

PropertyType just defined the allowed types for the properties. Then ConstructorType is a type defined to check if the passed type is one of these and return the corresponding type.

If using strings instead of constructors this could just be a type like

type PrimitiveTypeMap = {
  string: string;
  number: number;
  boolean: boolean;
  // ...etc
};

can easily add any primitives, but this is besides is besides the point.

Then you need a type that takes the object, here again we make the assumption that the object is of type record with string keys and values of the type {type:PropertyType }

type InferObjectSchema&lt;T extends Record&lt;string, { type: PropertyType }&gt;&gt; = {
  [K in keyof T]: ConstructorType&lt;T[K][&quot;type&quot;]&gt;;
};

This just creates a mapped type that applies the previously defined type to each value in the object.

Here's playground link

huangapple
  • 本文由 发表于 2023年7月18日 06:29:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76708464.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定