当类型B以某种方式“扩展”类型A时,如何停止TypeScript错误“类型A与类型B没有共同的属性”

时间:2019-12-19 11:27:57

标签: javascript reactjs typescript

(标题经过编辑,使其更笼统)

我正在使用在各处使用 React 类组件和 Typescript 的代码库,并且我正在尝试实现react-dropzone(轻巧,简单但有效的文件放置组件)使用基于类的方法。 Hooks的实现更加简洁明了,但我还是希望避免使用,以便保留其余代码中维护的范例。

在此模块的所有自述文本中,它均使用纯Javascript。这是一个典型的例子:

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>

这似乎是一个非常不寻常的语法...

我发现我不能只在Typescript中使用这个惯用法,所以我尝试使用以下方法使其工作:

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>
        );
    }
}

但是,短毛绒在<input>标签上引发了以下错误: Type '{ refKey?: string | undefined; }' has no properties in common with type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'. ts(2559)

有关更多信息,请参见相关的 react-dropzone 包中的Typescript定义:

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;
}

我真的不确定如何解决此问题-我对Typescript比较陌生。其他Stackoverflow解决方案即将推出,但不太适合这个问题。

预先感谢堆

@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"
  ]
}

这也是一个完整的例子:

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>
        );
    }

}

再次感谢

0 个答案:

没有答案