【问题标题】:React Typescript - dynamic typesReact Typescript - 动态类型
【发布时间】:2021-01-20 07:18:20
【问题描述】:

是否可以有动态类型?我有一个这样的json

{
  "fieldName": "Some text",
  "type": String,
  "inputType": "text"
},
{
  "fieldName": "Some bool",
  "type": Boolean,
  "inputType": "checkbox
}

基于该 json,我想渲染像这样的字段组件

const Field: React.FC<FieldInterface> = ({ name, type, handler }) => {
  const [value, setValue] = useState<type>()

  const handleOnChane = (e: ChangeEvent<HTMLInputElement>) => {
    setValue(e.target.value)
    handler(name, e.target.value)
  }

  return (
    <div>
      <label htmlFor={name}>{name}</label>
      <input
        type={type}
        id={name}
        onChange={handleOnChane}
        value={value}
      ></input>
    </div>
  )
}
export default Field

这是我的界面

export interface FormInterface {
  fields: FieldPropInterface[]
  submitAction: Function
}

export interface FieldPropInterface {
  name: string
  inputType: string
  type: <Here I would like to have something but don't know what>
}

export interface FieldInterface {
  name: string
  type: string
  handler: Function
}

你看,我需要那个类型来设置 useState 钩子变量的类型。 有可能吗?

回购链接: https://github.com/johnathan-codes/react-form-from-json

【问题讨论】:

  • 你已经看过 typescript typeof 操作符了吗?
  • 考虑阅读 typescript 文档。这是基础知识的基础。
  • @A_A 但这并不能将像 String 这样的构造函数解析为 string 类型——你仍然依赖于你提供的类型。 OP 正在尝试使用运行时信息进行静态类型化。
  • 我认为你真正想要的是一个union type,它强制属性 inputType 和 type 之间的关系。

标签: javascript reactjs typescript types


【解决方案1】:

其他响应会起作用,但它们没有利用 typescript 的全部功能。您需要在字段inputTypetype 之间建立关系,使得{inputType: "checkbox"} 的字段必须始终为boolean{inputType: "text"} 必须始终为string,等等。

下面是使用 a Union Type 的方法(您也可以使用映射或条件,但我不会涉及)。

type FieldPropInterface = {
    fieldName: string;
} & ({
    type: "string";
    inputType: "text";
} | {
    type: "boolean";
    inputType: "checkbox";
})

您需要更多地阅读the HTML input element 及其道具,因为您希望以不同于文本输入的方式处理复选框。复选框通过称为checkedboolean 属性而不是字符串value 设置它们的值。 npm 上还有很多包可以让处理表单变得更加容易。

如果您希望 useState 是通用的,那么您的组件 Field 应该是通用的。

您还说过您的FieldInterface.handler 可以是任何类型的Function,但您需要具体说明该功能是什么。

{ handler: (e: ChangeEvent<HTMLInputElement>) => void; }

或者它可以成为value 的函数,而不是event 的函数,但设置不同。

在使用大写名称String 时,您确定知道自己在做什么吗?大写的名称意味着值是 String 构造函数,而小写的意味着值是string。来自the docs

永远不要使用 Number、String、Boolean、Symbol 或 Object 类型 这些类型指的是几乎从不存在的非原始盒装对象 在 JavaScript 代码中适当使用。

如果你使用 this 作为标志,只是说“这个值是一个字符串”或“这个值是一个布尔值”,你可以考虑使用文字字符串 "string""boolean" 而不是对象构造函数,但我不知道在您的代码中实际使用的位置和方式。

【讨论】:

  • 感谢您的回答。你帮了我很多。我正在尝试创建自己的表单生成器,而不使用 3rd 方库。我在问题中添加了一个 repo 链接,也许它会让我的问题更清楚,我不擅长解释我不完全理解的东西。
【解决方案2】:

使用替代类型。

export interface FieldPropInterface {
  name: string;
  inputType: string;
  type: Boolean | String;
}

【讨论】:

    【解决方案3】:

    你也可以这样做:

    export interface FieldInterface<T> {
      name: string
      type: T
      handler: Function
    }
    
    const Field: React.FC<FieldInterface<typeof type>> = ({ name, type, handler }) => {
      const [value, setValue] = useState<type>()
    
      const handleOnChane = (e: ChangeEvent<HTMLInputElement>) => {
        setValue(e.target.value)
        handler(name, e.target.value)
      }
    
      return (
        <div>
          <label htmlFor={name}>{name}</label>
          <input
            type={type}
            id={name}
            onChange={handleOnChane}
            value={value}
          ></input>
        </div>
      )
    }
    export default Field
    

    【讨论】:

    • 这不是要走的路,你不能在运行时改变界面。
    • 那你就只有这种使用方式了-type: Boolean | String;
    • 没错。这就是我在上面发布的内容。
    猜你喜欢
    • 2019-01-22
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    • 2020-05-25
    • 2020-04-03
    • 2022-08-07
    • 2022-01-23
    相关资源
    最近更新 更多