I got such a piece of code in my React component:
type TLang = 'tur' | 'eng';
const [filterState, setFilterState] = useState<{
[key in TLang]: string | null;
}>(null);
const inputChangeHadnler =
(type: TLang): React.ChangeEventHandler<HTMLInputElement> =>
(event) => {
setFilterState({ [type]: event.target.value });
};
return <input onChange={inputChangeHadnler('tur')}></input>}
the line with the setFilterState states an error:
Argument of type '{ [x: string]: string; }' is not assignable to parameter of type 'SetStateAction<{ tur: string; eng: string; }>'. Type '{ [x: string]: string; }' is missing the following properties from type '{ tur: string; eng: string; }': tur, engts(2345)
As I understand, it shows the filrerstate object must have two properties: tur and eng, but I want it to have only one key, tur or eng, from the TLang type.
Are there any ways to say here: useState<{[key in TLang]: string | null;}>(null);
, that that object should have only one value: 'tur' or 'eng'?
My only idea is just to say: useState<{ tur: string | null } | { eng: string | null} | null>(null)>
, but I doubt it works if I have more languages.
CodePudding user response:
- The
event.target
can, in general, be any element. With TypeScript, use.currentTarget
so that TypeScript knows that the element being referred to is definitely the element the handler is attached to, rather than any of its children - that'll let it be inferred as an HTMLInputElement. - React generally works better with controlled components, and the same is true with TypeScript. Consider having a state for the input value that gets changed
onChange
of the input. inputChangeHadnler
should probably beinputChangeHandler
(typos are a frequent source of bugs in programming - fix them as soon as you see them to reduce confusion)
Are there any ways to say here: useState<{[key in TLang]: string | null;}>(null);, that that object should have only one value: 'tur' or 'eng'?
You could - { tur: string | null } | { eng: string | null }
- but instead to implement that sort of logic, you might consider creating another state for which language is being used.
const App = () => {
const [inputValue, setInputValue] = useState('');
const [lang, setLang] = useState<TLang>('tur');
return <input value={inputValue} onChange={(e) => { setInputValue(e.currentTarget.value); }} />;
};
Now you have two very easy to manage string states - the input value, and the language. If you need to create a filterState
object somewhere, you can now do so on demand from the existing states.
CodePudding user response:
Maybe defining state type as optional for every lang would help?
It should handle adding more languages.
Check demo Codesanbox example