reactjs - 如何在 Typescript 中强制覆盖现有类型?
我正在使用 Formik,一个 React 表单库,并创建我自己的自定义字段。我依赖于 Formik 的通用 Schema 类型,它表示他们的 values 对象,该对象包含表单中所有字段的所有值。
自定义组件是接收 FormikProps 的 checkboxgroup 组件
type FormikProps<Schema> = {
...
values: Schema
}
type Groceries = Array<{
id: string;
value: string;
}>
type Schema = {
...
firstName: string;
lastName: string;
groceries: Groceries
}
type Props<Schema> = {
...
name: keyof Schema & string;
} & FormikProps<Schema, unknown>
type State = {
isBananaSelectedInGroceries: boolean;
}
const getInitialState = (props: Props) => {
const groceries = props.values["groceries"];
// Property 'map' does not exist on type 'Schema[keyof Schema & string]'.ts(2339)
const values = groceries.map(({ value }) => value);
...
}
export class CheckboxGroup<Schema> extends React.Component<
Props<Schema>,
State
> {
state = getInitialState(this.props);
...
}
在 getInitialState 中,TypeScript 抱怨 groceries 不是一个数组。所以为了强行覆盖类型,我尝试了这个方法:
// Type 'Schema[keyof Schema & string]' is not assignable to type 'Groceries'.
// Type 'Schema[string]' is not assignable to type '{ id: string; value: string; }[]'.ts(2322)
const groceries: Groceries = props.values["groceries"];
const values = groceries.map(({ value }) => value);
我可以这样进行类型转换,然后错误就消失了——但这显然不是理想的做法:
const groceries: Groceries = (props.values["groceries"] as unknown) as Groceries;
const values = groceries.map(({ value }) => value);
这里发生了什么?为什么 TypeScript 没有推断出
values["groceries"]是一个Array?在这里让 Typescript 满意的理想方法是什么?
答案#1
你的 TypeScript 声明中有一些错误。修复它们之后,一切都按预期工作:Playground 链接
主要问题是 const getInitialState=(props: Props),因为 Props 是一个泛型类型(但它不需要是泛型,至少在当前的实现中不需要)。
通常你应该只在需要动态更改它们时使用泛型(例如使用 T,而不是具体类型,因为那可能会造成混淆)。
type FormikProps = {
values: Schema
}
type Groceries = Array<{
id: string;
value: string;
}>
type Schema = {
firstName: string;
lastName: string;
groceries: Groceries
}
type Props = {
name: keyof Schema & string;
} & FormikProps
type State = {
isBananaSelectedInGroceries: boolean;
}
const getInitialState = (props: Props) => {
const groceries = props.values["groceries"];
const values = groceries.map(({ value }) => value);
}
