简体   繁体   中英

How to stop TypeScript error 'Type A has no properties in common with Type B' when Type B "extends" Type A in some way

(edited Title to make more general)

I'm working in a codebase which uses React class components and Typescript everywhere, and I'm trying to implement react-dropzone (a lightweight, simple but effective file-drop component) using the class-based method. The Hooks implementation is cleaner and simpler but I'd prefer to avoid so as to preserve the paradigm maintained in the rest of the code.

In all the README text for this module, it uses plain Javascript. Here's a typical example:

import React from 'react'
import Dropzone from 'react-dropzone'

<Dropzone onDrop={acceptedFiles => console.log(acceptedFiles)}>
  {({getRootProps, getInputProps}) => (
    <section>
      <div {...getRootProps()}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop some files here, or click to select files</p>
      </div>
    </section>
  )}
</Dropzone>

This seems a fairly unusual syntax anyway...

I've discovered that I can't just use this idiom unchanged in Typescript, so I am trying to get it to work using the following:

import Dropzone, { DropzoneState } from "react-dropzone";

//...

export class BasicDropzone extends React.Component {
   onDrop = (files: Array<File>) => {
        console.log(files);
        this.files = files;
   }
//...
    render() {
//...
        return (
            <Dropzone onDrop={this.onDrop}>
                {(state: DropzoneState) => {
                    return (
                    <section className={styles.container}>
                        <div {...state.getRootProps({className: styles.dropzone})}>
                            <input {...state.getInputProps()} />
                         {/* ^^^^^ error here */}

                            <p>Drag and drop here, or click to select files</p>
                        </div>
                        <aside>
                            <h4>Files</h4>
                            <ul>{files}</ul>
                        </aside>
                    </section>
                )}}
            </Dropzone>
        );
    }
}

However the linter throws up the following error on the <input> tag: Type '{ refKey?: string | undefined; }' has no properties in common with type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'. ts(2559) Type '{ refKey?: string | undefined; }' has no properties in common with type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'. ts(2559)

Just for further info, here are the Typescript definitions from the react-dropzone package of relevance:

export type DropzoneState = DropzoneRef & {
  isFocused: boolean;
  isDragActive: boolean;
  isDragAccept: boolean;
  isDragReject: boolean;
  isFileDialogActive: boolean;
  draggedFiles: File[];
  acceptedFiles: File[];
  rejectedFiles: File[];
  rootRef: React.RefObject<HTMLElement>;
  inputRef: React.RefObject<HTMLInputElement>;
  getRootProps(props?: DropzoneRootProps): DropzoneRootProps;
  getInputProps(props?: DropzoneInputProps): DropzoneInputProps;
};

export interface DropzoneRef {
  open(): void;
}

export interface DropzoneRootProps extends React.HTMLAttributes<HTMLElement> {
  refKey?: string;
  [key: string]: any;
}

export interface DropzoneInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
  refKey?: string;
}

I'm really not sure how I can fix this - I'm relatively new to Typescript. Other Stackoverflow solutions come close but don't quite fit this issue.

Thanks heaps in advance

@zydnar:

{
  "compilerOptions": {
    "outDir": "build/dist",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "experimentalDecorators": true,
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,

    // See https://github.com/rexxars/react-markdown/issues/207
    "allowSyntheticDefaultImports": true,

    // See https://stackoverflow.com/questions/52399839/typescript-duplicate-identifier-librarymanagedattributes
    // for the reason for this.
    "skipLibCheck": true,
    "baseUrl": "."
  },
  "exclude": [
    "node_modules",
    "build",
    "scripts/*.js",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts"
  ]
}

Also here's a complete example:

import React from "react";
import { observable, action } from 'mobx';
import { observer } from 'mobx-react';
import Dropzone, { DropzoneState } from "react-dropzone";

//const styles = require('./dropzone.css');

@observer
export class BasicDropzone extends React.Component {
    @observable files: Array<File> = [];
    @action onDrop = (files: Array<File>) => {
        console.log(files);
        this.files = files;
    }

    render() {
        const files = this.files.map((file: File) => (
            <li 
                key={file.name}
          >
            {file.name}
          </li>
        ));
        return (
            <Dropzone onDrop={this.onDrop}>
                {(state: DropzoneState) => (
                    <section className={"container"}>
                        <div {...state.getRootProps({className: "dropzone"})}>
                            <input {...state.getInputProps() } />
                            <p>Drag and drop here, or click to select files</p>
                        </div>
                        <aside>
                            <h4>Files</h4>
                            <ul>{files}</ul>
                        </aside>
                    </section>
                )}
            </Dropzone>
        );
    }

}

Thanks again

我遇到了同样的问题,并且能够通过为<input/>元素提供typevalue来规避它,如评论中所述:

<input {...getInputProps()} type="file" value={files} />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM