react-filepond icon indicating copy to clipboard operation
react-filepond copied to clipboard

Typescript incompatibility with onupdatefiles and files props

Open anthonysgro opened this issue 1 year ago • 6 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Have you updated React FilePond, FilePond, and all plugins?

  • [X] I have updated FilePond and its plugins

Describe the bug

I am a new adopter of this library, and I am using typescript. However, I cannot figure out how to have my files in state match the type demanded by onupdatefiles.

Reproduction

export default function FreePollForm() {
    // State for the file input
    const [files, setFiles] = useState<Array<FilePondInitialFile | File | Blob | string>>([]);
    const [formData, setFormData] = useState({});
    
    const filepondRef = useRef<FilePond>(null)

    return (
                <FormItem>
                <FormLabel>Image</FormLabel>
                    <FormControl>
                        <FilePond
                            ref={filepondRef}
                            files={files}
                            onupdatefiles={setFiles}
                            allowMultiple={false}
                            name="files"
                            labelIdle='Drag & Drop your files or <span className="filepond--label-action">Browse</span>'
                        />
                    </FormControl>
            </FormItem>
    )

Here I am getting an error with onupdatefiles:

No overload matches this call.
  Overload 1 of 2, '(props: FilePondProps): FilePond', gave the following error.
    Type 'Dispatch<SetStateAction<(string | Blob | FilePondInitialFile | File)[]>>' is not assignable to type '(files: FilePondFile[]) => void'.
      Types of parameters 'value' and 'files' are incompatible.
        Type 'FilePondFile[]' is not assignable to type 'SetStateAction<(string | Blob | FilePondInitialFile | File)[]>'.
          Type 'FilePondFile[]' is not assignable to type '(string | Blob | FilePondInitialFile | File)[]'.
            Type 'FilePondFile' is not assignable to type 'string | Blob | FilePondInitialFile | File'.
              Property 'options' is missing in type 'FilePondFile' but required in type 'FilePondInitialFile'.
  Overload 2 of 2, '(props: FilePondProps, context: any): FilePond', gave the following error.
    Type 'Dispatch<SetStateAction<(string | Blob | FilePondInitialFile | File)[]>>' is not assignable to type '(files: FilePondFile[]) => void'.ts(2769)

And when I switch the setFiles type to

    const [files, setFiles] = useState<Array<FilePondFile>>([]);

I get an error on the files prop:

No overload matches this call.
  Overload 1 of 2, '(props: FilePondProps): FilePond', gave the following error.
    Type 'FilePondFile[]' is not assignable to type '(string | Blob | FilePondInitialFile | ActualFileObject)[]'.
      Type 'FilePondFile' is not assignable to type 'string | Blob | FilePondInitialFile | ActualFileObject'.
        Property 'options' is missing in type 'FilePondFile' but required in type 'FilePondInitialFile'.
  Overload 2 of 2, '(props: FilePondProps, context: any): FilePond', gave the following error.
    Type 'FilePondFile[]' is not assignable to type '(string | Blob | FilePondInitialFile | ActualFileObject)[]'.ts(2769)

So I am not entirely sure what to do here since they are expecting two different types but they handle the same objects

Environment

- Device: MacOs M1
- OS: Sonoma 14.5
- Broser: Firefox 126.0
- React version: 18

anthonysgro avatar Jun 04 '24 05:06 anthonysgro

As a workaround I am coercing typescript into thinking the types are correct. though this works for now, idk if there are going to be unforeseen problems later with this:

                        <FilePond
                            ref={filepondRef}
                            files={files}
                            onupdatefiles={(fileItems: FilePondFile[]) => {
                                setFiles(
                                    fileItems.map(
                                        (fileItem) => fileItem.file as File,
                                    ),
                                )
                            }}
                            allowMultiple={false}
                        />

anthonysgro avatar Jun 04 '24 05:06 anthonysgro

@anthonysgro Hey, I'm unfortunately not proficient enough in TypeScript to solve this based on the descriptions above. I guess coercing will work for now and I don't see that causing any issues.

rikschennink avatar Jun 04 '24 15:06 rikschennink

I ran into this also and it took me awhile to figure out how to get the sample above working since the FilePondFile wasn't exportable by react-filepond. Finally got it working with

import { FilePondFile, FilePondInitialFile } from 'filepond'

Thanks @anthonysgro for the fix!

@rikschennink Maybe a sample/help on the docs could be a fix in the meantime. I just copied the example from the site for react but hit type errors and this ticket helped me solve it! So like even just a If using react, you'll need to do this... sort of thing.

OscarGodson avatar Oct 17 '24 23:10 OscarGodson

@OscarGodson Thanks for the suggestion, I've updated the docs with a short annotation.

rikschennink avatar Oct 18 '24 09:10 rikschennink

This is what I did in my case.

import { FilePondFile } from 'filepond';
...
const [files, setFiles] = useState<File[]>([]);
...
 <FilePond
  files={files}
  onupdatefiles={(fileItems: FilePondFile[]) => {
    setFiles(fileItems.map((f: FilePondFile) => f.file as File));
  }}
  allowMultiple={true}
  maxFiles={3}
  server="/api"
  name="files"
  labelIdle='Drag & Drop your files or <span class="filepond--label-action">Browse</span>'
/>
...

arantebw avatar Nov 21 '24 03:11 arantebw

Thanks @arantebw, it looks like this is the clean way to solve the issue.

The core filepond code states that they plan to transition from ActualFileObject to the native File type, at which point the undesired as File cast will no longer be necessary.

// TODO replace all references to `ActualFileObject` with native `File`
/**
 * @deprecated Don't use this type explicitly within your code. It'll be replaced with the native `File` type in a future release.
 */
export type ActualFileObject = Blob & { readonly lastModified: number; readonly name: string };

https://github.com/pqina/filepond/blob/afebde20f4d0cffa09ff18dbf8d79c2c1d5a1d80/types/index.d.ts#L35-L39

jchook avatar Mar 05 '25 23:03 jchook