React – TypeScript泛型响应类型的问题

huangapple go评论74阅读模式
英文:

React - Typescript problem with generic response type

问题

我有以下的TypeScript类型:

export type Response<T> = { isSuccess: true; data: T } | { isSuccess: false; error: string };

export interface IItems {
    item1: IItemObject[]
    item2: IItemObject[]
}

然后在我的React代码中,我从API获取数据:

获取结果如上述的 "Response" 类型:

如果 isSuccess === true,将响应存储到状态:

const [savedItems, setSavedItems] = useState<{number: number, items: Response<IItems>}[] | undefined>();

所以我的问题出现在尝试像这样访问响应的 "data" 对象时:

savedItems?.find((a: any) => a.number === inputNumber)?.items?.data?.item1

我得到以下的TypeScript错误:

Property 'data' does not exist on type 'Response<IItems>'.
  Property 'data' does not exist on type '{ isSuccess: false; error: string; }'.ts(2339)

即使尝试使用类型保护也会得到相同的错误:

const typeGuardTest = savedItems?.find((a: any) => a.number === inputNumber)?.items?.isSuccess
? (savedItems.find((a: any) => a.number === inputNumber)?.items.data?.item1)
: undefined;

有任何想法可能出现问题的地方吗?

英文:

I have Following typescript types:

export type Response&lt;T&gt; = { isSuccess: true; data: T } | { isSuccess: false; error: string };

and

export interface IItems {
    item1: IItemObject[]
    item2: IItemObject[]
}

Then in my react code I fetch data from api -->

Get result as the above "Response" type -->

And if isSuccess === true, response is stored into a state:

const [savedItems, setSavedItems] = useState&lt;{number: number, items: Response&lt;IItems&gt;}[] | undefined&gt;();

So my problem comes when trying to access the responses "data" object like this:

savedItems?.find((a: any) =&gt; a.number === inputNumber)?.items?.data?.item1

I get the following typescript error:

Property &#39;data&#39; does not exist on type &#39;Response&lt;IItems&gt;&#39;.
  Property &#39;data&#39; does not exist on type &#39;{ isSuccess: false; error: string; }&#39;.ts(2339)

I get the same error even when trying to use type guard like this:

const typeGuardTest = savedItems?.find((a: any) =&gt; a.number === inputNumber)?.items?.isSuccess
? (savedItems.find((a: any) =&gt; a.number === inputNumber)?.items.data?.item1)
: undefined;

Any idea where the problem might be?

答案1

得分: 1

Response 返回一个联合类型,其中只有成功响应具有 data 属性。

您需要检查 savedItems.items 是否是成功响应:

if(savedItems.items.isSuccess) {
}

如果 isSuccess 为真,则 TypeScript 将能够推断 savedImages 是成功响应,您将能够使用 data:

const response: { items: Response<IItems> } = {
  items: {
    isSuccess: true,
    data: { item1: [], item2: [] },
  },
};

if (response.items.isSuccess) {
  response.items.data.item1.find((v) => v);
}
英文:

Since Response returns a union where only the success response has data property.

You need to check whether the savedItems.items is a success response:

if(savedItems.items.isSuccess) {
}

And if the isSuccess true then the typescript will be able to infer that savedImages is a success response and you'll be able to use data:

const response: { items: Response&lt;IItems&gt; } = {
  items: {
    isSuccess: true,
    data: { item1: [], item2: [] },
  },
};

if (response.items.isSuccess) {
  response.items.data.item1.find((v) =&gt; v);
}

huangapple
  • 本文由 发表于 2023年6月26日 20:17:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76556605.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定