javascript - วิธีขยายคลาส React ใน typescript
นี่คือตัวอย่างง่ายๆ:
interface BaseProps {
name: string;
}
class BaseClass<P extends BaseProps> extends React.Component<P, void> {
}
interface SuperProps {
}
class SuperClass extends BaseClass<SuperProps> {
}
ฉันคาดหวังว่า SuperClass จะมี this.props.name โดยค่าเริ่มต้น แต่ตอนนี้ฉันได้รับข้อผิดพลาดในการคอมไพล์ โดยบอกว่า Type 'SuperProps' does not satisfy the constraint 'BaseProps'. Property 'name' is missing in type 'SuperProps'.
ฉันทำอะไรผิดหรือเปล่า? ฉันเข้าใจว่าฉันสามารถทำ SuperProps extends BaseProps ได้ แต่ดูเหมือนว่าที่นี่จะซ้ำซ้อน.
คำตอบ #1
class BaseClass<P extends BaseProps> extends React.Component<P, void>
ที่ <P extends BaseProps> หมายถึงชนิดใด ๆ ที่ถูกต้องซึ่งขยาย BaseProps สามารถกำหนดค่าให้กับ BaseClass ได้ นี่คือวิธีที่เจนเนอริกทำงาน
ตอนนี้ เมื่อคุณทำ
interface SuperProps {
}
class SuperClass extends BaseClass<SuperProps> {
}
คุณกำลังกำหนดประเภท SuperProps ซึ่งไม่ได้สืบทอดจาก BaseProps นั่นคือเหตุผลที่คุณได้รับข้อผิดพลาด
ในการแก้ไขข้อผิดพลาด ตามที่คุณบอก คุณจำเป็นต้องขยายอินเทอร์เฟซ BaseProps หรือคุณสามารถใช้ชนิด intersection ถ้าคุณใช้ชนิด intersection ตัวอย่างสมบูรณ์จะมีลักษณะดังนี้:
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>
);
}
}
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับประเภทขั้นสูงได้ที่นี่
คำตอบ #2
ตอนนี้ลองพูดว่าคุณไม่สามารถแก้ไข BaseClass (โค้ดของบุคคลที่สาม) ให้รองรับชนิดทั่วไปได้ เช่น
class BaseClass extends React.Component<BaseProps, void> {
}
คุณยังคงสามารถนิยามใหม่ BaseClass ด้วยประเภทพร็อพที่ขยายออกไปได้ดังนี้:
const SuperClass = BaseClass as React.ComponentClass<
BaseProps & {
somethingElse: string;
}
>;
ตัวอย่างเต็ม เช่น ที่ SomeInput จริงๆ รองรับ prop autoFocus แต่ type defs ของ prop ที่ส่งออกไม่รองรับ:
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
