gpt4 book ai didi

reactjs - 从实用程序类型中解构 Prop (提取和排除 - TypeScript 和 React)

转载 作者:行者123 更新时间:2023-12-05 04:25:28 27 4
gpt4 key购买 nike

我遇到了 Typescript 和 React 的问题。

假设我有以下联合类型:

type Fruits = 'apple' | 'peach' | 'banana';

我是这样使用它的:

type FoodBaseProps = {
fruits: Fruits;
weight: number
price: number
}

现在,假设我有一个名为 needToPeel 的 bool 属性只有当水果 banana 才应该被告知已通过;

为了解决这个问题,我做了以下事情:

export type NeedToPeelFruitsProps = FoodBaseProps & {
fruits: Extract<Fruits, 'banana'>;
needToPeel?: boolean;
};

对于其他不需要去皮的水果,我有:

export type DefaultFruitsProps = FoodBaseProps & {
fruits: Exclude<Fruits, 'banana'>;
};

然后我有:

type FoodProps = NeedToPeelFruitsProps | DefaultFruitsProps;

现在,如果我根据这个逻辑做一些断言,我会得到这个(按预期工作):

const testFn = (food: FoodProps) => {
switch (food.fruits) {
case 'banana': {
console.log(food.needToPeel); // No error
break;
}

case 'apple': {
console.log(food.needToPeel); // TS2339: Property 'needToPeel' does not exist on type 'DefaultFruitsProps'.
break;
}

default:
}
};

但是,如果我尝试访问这个 needToPeel prop 在我的 React 组件中,我会遇到一些问题:

const Food = ({
fruits,
weight,
price,
needToPeel, // TS2339: Property 'needToPeel' does not exist on type 'FoodProps'.
}: FoodProps) => {
return (
<FoodBase
fruits={fruits}
weight={weight}
price={price}
needToPeel={needToPeel} // 2 errors below
/>
)
}

1 - TS2769: No overload matches this call.   Overload 1 of 2, '(props: Omit<Omit<Pick<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "key" | keyof HTMLAttributes<...>> & { ...; } & [...] ;

2 - TS2339: Property 'needToPeel' does not exist on type 'FoodProps'.

我认为问题是因为联合类型只考虑共同的 Prop 。所以,needToPeel prop 将不可访问,因为它不在类型之间共享。

我想知道是否有办法访问 needToPeel在我的 React 组件中。

最佳答案

I think the problem is because union types only consider the props in common.

确实,当变量类型为联合时,the only safe thing we know is that it has the common properties .

TypeScript will only allow an operation if it is valid for every member of the union. For example, if you have the union string | number, you can’t use methods that are only available on string

访问特定属性的唯一安全方法是首先访问 narrow类型,例如就像在您的“断言”示例中一样。

The solution is to narrow the union with code, the same as you would in JavaScript without type annotations. Narrowing occurs when TypeScript can deduce a more specific type for a value based on the structure of the code.


if I try to access this needToPeel prop in my React component, I'll have some problems

那是因为如果我们从函数参数定义中对 React 功能组件进行典型的 props 解构(就像在问题示例中一样),那么这种解构发生得太早了。如果我们想要解构并获得特定的 needToPeel 属性,它必须在 类型缩小之后发生。

我认为这种情况是偏离此标准做法的正当理由:正如暗示的那样,从函数参数定义中解构 props 没有硬性技术要求;对于 React 功能组件来说,这是一种常见的做法;在 React 基于类的组件中,无论如何我们都必须使用 this.props

One of the very first examples React 文档中带有 props 的组件也不使用解构:

function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}

因此在您的情况下,您可以很好地将解构推迟到 类型缩小之后(或者甚至根本不解构):

const Food = (props: FoodProps) => {
// Narrowing
if (props.fruits === "banana") {
// Now TS knows that props is a NeedToPeelFruitsProps
return (
<FoodBase
fruits={props.fruits}
weight={props.weight}
price={props.price}
needToPeel={props.needToPeel} // Okay
/>
);
}
// Depending on the signature of <FoodBase>,
// you could even blindly pass the props,
// which may or may not have the needToPeel property
return (
<FoodBase
{...props}
/>
)
}

关于reactjs - 从实用程序类型中解构 Prop (提取和排除 - TypeScript 和 React),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73253080/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com