You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React应用中如何验证输入字符串匹配指定联合类型且便于后续扩展

React应用中如何验证输入字符串匹配指定联合类型且便于后续扩展

嗨,我太懂你的顾虑了——硬编码一堆===判断确实太不灵活,以后要加新的协议选项,得翻遍代码改判断逻辑,想想都麻烦。给你分享个既能满足TypeScript类型校验要求,又能轻松应对后续扩展的方案:

核心思路

把所有允许的协议值统一维护在一个数组里,基于这个数组做校验和类型守卫。这样以后新增协议,只需要更新数组和联合类型,完全不用动校验逻辑,扩展性拉满。

具体实现步骤

  • 首先定义联合类型和对应的允许值数组:

    type protocollType = 'http' | 'https';
    // 所有合法协议都存在这里,以后加新的直接追加就行
    const allowedProtocols: protocollType[] = ['http', 'https'];
    
  • 接着写一个类型守卫函数,让TypeScript能自动识别校验通过后的输入类型:

    function isProtocolValid(input: string): input is protocollType {
      // 用数组的includes方法做判断,类型断言是为了让TS不报错
      return allowedProtocols.includes(input as protocollType);
    }
    
  • 在React组件里的使用示例:
    你可以在输入变化或表单提交时调用这个守卫函数做校验,而且校验通过后,TypeScript会自动把输入值的类型收窄为protocollType,不用再担心类型不匹配的问题。

    import { useState } from 'react';
    
    type protocollType = 'http' | 'https';
    const allowedProtocols: protocollType[] = ['http', 'https'];
    
    function isProtocolValid(input: string): input is protocollType {
      return allowedProtocols.includes(input as protocollType);
    }
    
    function ProtocolInput() {
      const [inputValue, setInputValue] = useState('');
      const [isInputValid, setIsInputValid] = useState(false);
    
      const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const newValue = e.target.value.trim();
        setInputValue(newValue);
        // 实时校验输入合法性
        setIsInputValid(isProtocolValid(newValue));
      };
    
      const handleSubmit = (e: React.FormEvent) => {
        e.preventDefault();
        if (isInputValid) {
          // 这里inputValue已经被TS确认为protocollType类型,可安全使用
          alert(`你输入的有效协议是:${inputValue}`);
        } else {
          alert('请输入有效的协议类型(目前支持http或https)');
        }
      };
    
      return (
        <form onSubmit={handleSubmit} style={{ margin: '20px' }}>
          <label>
            输入协议:
            <input
              type="text"
              value={inputValue}
              onChange={handleInputChange}
              placeholder="例如:http"
              style={{
                marginLeft: '10px',
                padding: '5px',
                borderColor: isInputValid ? 'green' : 'red',
                outline: 'none'
              }}
            />
          </label>
          <button 
            type="submit" 
            disabled={!isInputValid}
            style={{ marginLeft: '10px', padding: '5px 10px' }}
          >
            确认
          </button>
        </form>
      );
    }
    
    export default ProtocolInput;
    

扩展优势

以后如果要新增支持的协议,比如'ftp',只需要做两处简单修改:

  1. 更新联合类型:type protocollType = 'http' | 'https' | 'ftp';
  2. allowedProtocols数组里追加'ftp'const allowedProtocols: protocollType[] = ['http', 'https', 'ftp'];
    校验逻辑完全不用碰,是不是特别省心?

备注:内容来源于stack exchange,提问作者dwiandan

火山引擎 最新活动