मैं कुछ ऑब्जेक्ट प्राप्त करना चाहता हूं और इसे चाबियों द्वारा स्ट्रिंग्स और रिटर्न ऑब्जेक्ट के रूप में संशोधित करना चाहता हूं।

const useInputs = <T extends Record<string, string>>(defaultValue: T) => {
    const [inputsData, setInputsData] = useState<T>(defaultValue)

    type UpdateFunction = (key: string) => (el: React.FocusEvent<HTMLInputElement>) => void
    const updateData: UpdateFunction = key => el => {
        const newInputsData = {...inputsData}
        newInputsData[key] = el.target.value
        setInputsData(newInputsData)
    }

    return { inputsData, updateData }
}

लेकिन मुझे newInputsData[key] = el.target.value पर त्रुटि है "टाइप 'स्ट्रिंग' का उपयोग इंडेक्स टाइप 'T'.ts(2536) के लिए नहीं किया जा सकता है"

मैं इसे कैसे ठीक कर सकता हूं? धन्यवाद

2
Petr Tcoi 19 जुलाई 2020, 10:28

1 उत्तर

सबसे बढ़िया उत्तर

त्रुटि इसलिए आती है क्योंकि सामान्य प्रकार T को किसी भी प्रकार से त्वरित किया जा सकता है जो Record<string, string> का विस्तार करता है।

प्रकार पर विचार करें

interface Inputs {x: string; y: string} 

जबकि Inputs, Record<string, string> का विस्तार करता है, यह पूरी तरह से असुरक्षित होगा कि इसे मनमाने ढंग से अनुक्रमित करने की अनुमति दी जाए।

दूसरे शब्दों में, हम निम्नलिखित नहीं चाहेंगे

const i: Inputs = {x: "A", y: "B"};
const [inputs, setInputs] = useInputs(i);
setInputs("name")(event);

क्योंकि Inputs के पास name प्रॉपर्टी नहीं है।

इसलिए, आपके आंतरिक प्रकार, UpdateFunction, को एक तर्क लेना चाहिए जो कि किसी भी प्रकार के T को किसी भी तात्कालिकता के लिए एक वैध कुंजी है। इस प्रकार को keyof T के रूप में (key: keyof T) => (el: React.FocusEvent<HTMLInputElement>) => void में लिखा जाता है।

इसे एक साथ रखकर इसे इस तरह दिखना चाहिए

const useInputs = <T extends Record<string, string>>(defaultValue: T) => {
    const [inputsData, setInputsData] = useState<T>(defaultValue);

    type UpdateFunction = (key: keyof T) => (el: {target: {value: T[keyof T]}}) => void;
    const updateData: UpdateFunction = key => el => {
        const newInputsData = {...inputsData};
        newInputsData[key] = el.target.value;
        setInputsData(newInputsData)
    };

    return [inputsData, updateData] as const;
};

बाहरी फ़ंक्शन के रिटर्न वैल्यू में समायोजन पर ध्यान दें जो आपके हुक के पारंपरिक उपयोग की अनुमति देता है।

const [inputs, setInputs] = useInputs(...);

अपरंपरागत के विपरीत

const {inputsData, updateData} = useInputs(...);

इसके अलावा, ध्यान दें कि उपरोक्त टाइपचेक करने के लिए, हमें दूसरे पैरामीटर के प्रकार को भी समायोजित करना पड़ा, el, जो React से संपत्ति को अपडेट करने के लिए मान प्रदान करता है। फोकसइवेंट से {target: {value: T[keyof T]}} इसी कारण से ऊपर चर्चा की गई है, जेनेरिक T के साथ त्वरित किया जा सकता है गुण जिनके मान स्ट्रिंग के उपप्रकार हैं जैसे "निराशा" और "elation"

विकल्पों में el के लिए अधिक सटीक प्रकार का उपयोग करना शामिल है जैसे

Omit<React.FocusEvent<HTMLInputElement>, "target"> & {
  target: { value: T[keyof T] };
}

कैसे useInput को बदलना सामान्य है, संपूर्ण इनपुट ऑब्जेक्ट के प्रकार से लेकर उस ऑब्जेक्ट की केवल प्रॉपर्टी कुंजियों तक।

const useInputs = <K extends string>(defaultValue: Record<K, string>) => {
  const [inputsData, setInputsData] = useState(defaultValue);

  type UpdateFunction = (
    key: K
  ) => (el: React.FocusEvent<HTMLInputElement>) => void;
  const updateData: UpdateFunction = key => el => {
    const newInputsData = { ...inputsData };
    newInputsData[key] = el.target.value;
    setInputsData(newInputsData);
  };

  return [inputsData, updateData] as const;
};

मैं इसे अंतिम पसंद करता हूं, क्योंकि HTMLInputElement का value हमेशा एक string होता है।

2
Aluan Haddad 13 सितंबर 2020, 07:44