javascript - Hur man utökar en React-klass i TypeScript


Här är ett enkelt exempel:

interface BaseProps {
    name: string;
}

class BaseClass<P extends BaseProps> extends React.Component<P, void> {

}

interface SuperProps {

}

class SuperClass extends BaseClass<SuperProps> {

} 

Jag förväntar mig att SuperClass som standard skulle ha this.props.name. Men just nu får jag ett kompileringsfel som säger Typen 'SuperProps' uppfyller inte begränsningen 'BaseProps'. Egenskapen 'name' saknas i typen 'SuperProps'.

Vad gör jag fel? Jag inser att jag kan göra SuperProps extends BaseProps men det verkar överflödigt här.

Svar #1

class BaseClass<P extends BaseProps> extends React.Component<P, void>

där <P extends BaseProps> betyder vilken giltig typ som helst som utökar BaseProps kan tilldelas till BaseClass. Så fungerar generics.

Nu, när du gör

interface SuperProps {

}

class SuperClass extends BaseClass<SuperProps> {

} 

Du tilldelar typen SuperProps som inte utökar BaseProps. Det är anledningen till att du får felet.

För att övervinna felet, som du sa, behöver du antingen utöka BaseProps-gränssnittet eller använda snitt-typer. Om du använder snitt-typer kommer hela exemplet att se ut så här:

export interface BaseProps {
    name: string;
}

class BaseClass<P> extends React.Component<P & BaseProps, void> {

}

interface SuperProps {

}

class SuperClass extends BaseClass<SuperProps> {
    render(): JSX.Element {
        return (
            <div>
                {this.props.name} {/* Won't throw an error*/}
            </div>
        );
    }
}

Du kan läsa mer om avancerade typer här.

Svar #2

Säg nu att du inte kunde modifiera BaseClass (tredjepartskod) så att det tar en generisk typ, dvs.

class BaseClass extends React.Component<BaseProps, void> {

}

Du bör fortfarande kunna omdefiniera BaseClass med utökade proptyper på följande sätt:

const SuperClass = BaseClass as React.ComponentClass<
  BaseProps & {
    somethingElse: string;
  }
>;

Fullt exempel där SomeInput faktiskt stöder autoFocus-egenskapen men dess exporterade egenskapstypsdefinitioner gör det inte:

import { Input as SomeInput, InputPropsType as SomeInputPropsType } from 'somewhere';

const Input = SomeInput as React.ComponentClass<
  SomeInputPropsType & {
    autoFocus?: boolean;
  }
>;

// Now passing `autoFocus` prop to `Input` should be fine

Relaterade artiklar