如何让TS对接口类型进行推断

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

How to make TS make an inference on interface types

问题

当我尝试访问MessageImgTypes的textImg属性时,我收到一个错误消息,告诉我:
属性'textImg'在'type' 'MessageTypes | MessageImgTypes'上不存在
尽管这是一个联合类型,所以它应该存在于MessageImgType中,因为我在那里声明了它。
我考虑过进行类型缩小以创建两个分支,但typeof和instanceof不适用于这些接口。

英文:

I have this object that I created into my React application.

type Props = {
message: MessageTypes | MessageImgTypes;
showTimeStamp: boolean;
}

Assuming that MessageTypes is the following :

interface MessageTypes {
text: string;
};

and that MessageImgTypes is the following :

interface MessageImgTypes {
text?: string;
textImg : string;
};

When I try to access textImg property of MessageImgTypes, I get an error telling me that :
Property 'textImg' does not exist on type 'MessageTypes | MessageImgTypes'
Though this is a union, so it should exist on the MessageImgType since I've declared it in there.
I thought about doing Narrowing to make 2 branches but typeof and instanceof do not apply on these interfaces.

答案1

得分: 2

这个联合类型意味着message将是MessageTypesMessageImgTypes之一,由于在MessageTypes中没有'textImg',因此你会收到错误。

有几种方法可以解决这个问题。

  1. 使用in操作符:
    使用in操作符,我们可以检查对象中是否存在某个键,这将帮助编译器缩小类型:
if ('textImg' in message) {
   message.textImg // 没有错误
}
  1. 区分联合类型
    区分联合类型是一种联合类型,其中每个成员都具有一个具有唯一值的共同属性。检查该字段的值也会缩小类型,但需要更改接口的形状:
interface MessageTypes { text: string; type: 'one' };

interface MessageImgTypes { text?: string; textImg: string; type: 'two' };

if (message.type === 'two') {
   message.textImg // 没有错误
}
  1. 使用自定义类型守卫:
const isMessageImgTypes = (arg: MessageTypes | MessageImgTypes): arg is MessageImgTypes => {
   return 'textImg' in arg;
}
英文:

The union means that message will be either MessageTypes or MessageImgTypes and since there is no 'textImg' in the MessageTypes, and thus you get the error.

There are several approaches that we can take.

  1. Use the in operator:
    With the in operator we can check whether there is a key inside of the object, which will help the compiler to narrow the type:
if('textImg' in message) {
   message.textImg // no error
}
  1. Discriminated unions
    The discriminated union is a union where each member has one common property with a unique value. Checking the value of that field will also narrow the type, but will require changes in the shape of the interfaces:
interface MessageTypes { text: string; type: 'one' };

interface MessageImgTypes { text?: string; textImg : string; type: 'two' };

if(message.type === 'two') {
   message.textImg // no error
}
  1. Use a custom type guard:
const isMessageImgTypes = (arg: MessageTypes | MessageImgTypes): arg is MessageImgTypes => {
   return 'textImg' in arg;
}

huangapple
  • 本文由 发表于 2023年7月10日 20:33:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76653792.html
匿名

发表评论

匿名网友

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

确定