It all comes down to the unknown type of res
, introduced here:
const res = await Axios.get(`/api/movies/${currentMovie.movieId}/subtitles?user=${user.id}`);
res
is any
, which makes fields
type any
, which in turn makes formArray
be of type [string, unknown][]
, thus value
is unknown
, which causes the error.
To solve this problem at the source, we can use a generic type on the Axios.get
method like so:
const res = await Axios.get<{url :string, fields: {[key:string]:string}}>(`/api/movies/xxx/subtitles?user=xxx`);
This will make res
be of type {url :string, fields: {[key:string]:string}}
. This causes fields
to be of type {[key:string]:string}
.
Unfortunately the spread operator does not infer the right types. The code {...fields, file}
resolves to type {file: File}
, which is not really helpful. So let's hint formArray
:
const formArray : [string, string|File][] = Object.entries({...fields, file});
Now value
will be of type string|File
.
Full example:
function App() {
let fileInput = useRef<HTMLInputElement>(null);
const uploadSubtitle = async (e: React.FormEvent) => {
e.preventDefault();
const file = fileInput.current!.files![0];
const res = await Axios.get<{ url: string, fields: { [key: string]: string } }>(`/api/movies/xxx/subtitles?user=xxx`);
const {url, fields} = res.data;
const formData = new FormData();
const formArray: [string, string | File][] = Object.entries({...fields, file});
formArray.forEach(([key, value]) => {
formData.append(key, value);
});
};
return <form onSubmit={uploadSubtitle}>
<input type='file' name='subtitle' ref={fileInput} accept='.srt'/>
<button type="submit">Upload</button>
</form>
}
This is all rather a lot of work for something that can be fixed by changing the problematic line to:
formData.append(key, value as Blob);
Adding the as Blob
won't change the compiled JS but will make the typescript compiler stop complaining.