我測驗了一些包裝子組件的組件,并希望創建一個函式來渲染它們并添加一些子組件。我們如何在不失去型別安全性的情況下使用 Typescript 做到這一點?請參閱以下代碼中的注釋:
import * as React from "react";
import { render } from "@testing-library/react";
//function renderContainer<Props extends {children: React.ReactNode}>
function renderContainer<Props>(
Container: React.ComponentType<Props>,
props?: Props
) {
return render(
/*
Currently, we have this error here:
"Type '{ children: Element; }'is not assignable to type 'Props'.
'Props' could be instantiated with an arbitrary type which could
be unrelated to '{ children: Element; }"
If we constrain the`Props` type like <Props extends {children: React.ReactNode}>,
we get this error:
"Type '{ children: Element; }' is not assignable to type 'Props'.
'{ children: Element; }' is assignable to the constraint of type 'Props',
but 'Props' could be instantiated with a different subtype of constraint
'{ children: ReactNode; }'"
*/
<Container {...props}>
<div>Child</div>
</Container>
);
}
type CustomComponentProps = {
children?: React.ReactNode;
prop1: number;
prop2?: string;
};
const CustomComponent = ({ prop1, prop2, children }: CustomComponentProps) => (
<div>{children}</div>
);
// Expected behavior:
renderContainer(CustomComponent, { prop1: 1 }); // ok
renderContainer(CustomComponent, { prop1: 1, prop2: "string" }); // ok
renderContainer(CustomComponent, { prop3: 3 }); // error
代碼沙盒
uj5u.com熱心網友回復:
實際上,解決這個問題的更簡單的方法是renderContainer反過來思考,將泛型設定為它自己的組件型別,而不是道具。
type ReactComponent = JSXElementConstructor<any>;
type CustomComponentProps = {
children?: React.ReactNode;
prop1: number;
prop2?: string;
};
const CustomComponent = ({ prop1, prop2, children }: CustomComponentProps) => (
<div>{children}</div>
);
declare function renderContainer<T extends ReactComponent>(container: T, props: React.ComponentProps<T>): React.ReactNode
renderContainer(CustomComponent, { prop1: 1 }); // ok
renderContainer(CustomComponent, { prop1: 1, prop2: "string" }); // ok
renderContainer(CustomComponent, { prop3: 3 }); // error
這種方式更自然,因為您首先定義了組件是什么,然后 TypeScript 會推斷出 props,您甚至不必專門將任何泛型傳遞到函式中。
uj5u.com熱心網友回復:
這是一個作業版本。
道具需要擴展PropsWithChildren<any>,像這樣:
import * as React from "react";
import { render } from "@testing-library/react";
function renderContainer<Props extends React.PropsWithChildren<any>>(
//function renderContainer<Props>(
Container: React.ComponentType<Props>,
props?: Props
) {
return render(
<Container {...props}>
<div>Child</div>
</Container>
);
}
type CustomComponentProps = {
children?: React.ReactNode;
prop1: number;
prop2?: string;
};
const CustomComponent = ({ prop1, prop2, children }: CustomComponentProps) => (
<div>{children}</div>
);
// Expected behavior:
renderContainer(CustomComponent, { prop1: 1 }); // ok
renderContainer(CustomComponent, { prop1: 1, prop2: "string" }); // ok
renderContainer(CustomComponent, { prop3: 3 }); // error
/* Argument of type '({ prop1, prop2, children }: CustomComponentProps) => JSX.Element' is not assignable to parameter of type 'ComponentType<{ prop3: number; }>'.
Type '({ prop1, prop2, children }: CustomComponentProps) => JSX.Element' is not assignable to type 'FunctionComponent<{ prop3: number; }>'.
Types of parameters '__0' and 'props' are incompatible.
Property 'prop1' is missing in type 'PropsWithChildren<{ prop3: number; }>' but required in type 'CustomComponentProps'.ts(2345) /*
如果您想要道具而不是 CustomComponent 上的錯誤:
import * as React from "react";
import { render } from "@testing-library/react";
function renderContainer<Props extends React.PropsWithChildren<any>>(
//function renderContainer<Props>(
Container: React.ComponentType<Props>,
props?: Props
) {
return render(
<Container {...props}>
<div>Child</div>
</Container>
);
}
type CustomComponentProps = {
children?: React.ReactNode;
prop1: number;
prop2?: string;
};
const CustomComponent: React.ComponentType<CustomComponentProps> = ({ prop1, prop2, children }) => (
<div>{children}</div>
);
// Expected behavior:
renderContainer(CustomComponent, { prop1: 1 }); // ok
renderContainer(CustomComponent, { prop1: 1, prop2: "string" }); // ok
renderContainer(CustomComponent, { prop3: 3 }); // error
/* Argument of type '{ prop3: number; }' is not assignable to parameter of type 'CustomComponentProps'.
Object literal may only specify known properties, but 'prop3' does not exist in type 'CustomComponentProps'. Did you mean to write 'prop1'? /*
代碼沙盒
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/330857.html
上一篇:僅覆寫一些通用變數
