为什么我的TypeScript报告联合类型的错误?
我有: 其中:为什么我的TypeScript报告联合类型的错误?,typescript,typeguards,Typescript,Typeguards,我有: 其中: type: 'WEBSOCKET' | 'HTTP_STREAM'; connection: WebSocketType | HTTPStreamType; 我正在努力: interface Header { key: string; val: string; } export interface WebSocketType { websocketUrl: string; } export interface HTTPStreamType { streamU
type: 'WEBSOCKET' | 'HTTP_STREAM';
connection: WebSocketType | HTTPStreamType;
我正在努力:
interface Header {
key: string;
val: string;
}
export interface WebSocketType {
websocketUrl: string;
}
export interface HTTPStreamType {
streamUrl: string;
method: 'get' | 'put';
headers: Header[];
}
但我得到的错误是:
if (newStream.type === 'WEBSOCKET') {
if (newStream?.connection?.websocketUrl?.length > 0) {
return setIsNextDisabled(false)
}
}
我原以为
防护装置可以工作,但实际上不行。我想你应该有这样的装置:
Property 'websocketUrl' does not exist on type 'WebSocketType | HTTPStreamType'.
Property 'websocketUrl' does not exist on type 'HTTPStreamType'.
根据此界面,您可以拥有WEBSOCKET
的type
和HTTPStreamType
的connection
。你没有任何地方保证每个工会成员之间有任何联系<代码>类型
和连接都可以是联合体的任一成员
这就是为什么typescript认为你的守卫帮不上忙的原因
相反,你想要一种不同的联盟:
interface MyData {
type: 'WEBSOCKET' | 'HTTP_STREAM';
connection: WebSocketType | HTTPStreamType;
}
此类型表示MyData
可以是具有WebSocketType
连接的类型WEBSOCKET
,也可以是具有HTTPStreamType
连接的类型HTTP\u-STREAM
。但它永远不能将第一种财产和第二种财产混合在一起
现在,typescript可以推断,对其中一个属性的检查允许知道另一个属性类型
使用通过类型检查的代码
通过一些重构,您可以避免重复公共属性
联合类型必须有一些公共字段,在您的情况下,类似这样的东西可以工作
interface MyCommonData {
foo: string
bar: number
}
interface WebSocketData extends MyCommonData {
type: 'WEBSOCKET'
connection: WebSocketType
}
interface HttpStreamData extends MyCommonData {
type: 'HTTP_STREAM';
connection: HTTPStreamType;
}
type MyData = WebSocketData | HttpStreamData
您应该给出一个完整的(非)工作示例。那么,如果
MyData
更复杂,并且每个其他属性的类型都相同,该怎么办?我真的要定义它两次吗?一点也不!请参见“我的编辑”,末尾有一个游乐场链接。
interface MyCommonData {
foo: string
bar: number
}
interface WebSocketData extends MyCommonData {
type: 'WEBSOCKET'
connection: WebSocketType
}
interface HttpStreamData extends MyCommonData {
type: 'HTTP_STREAM';
connection: HTTPStreamType;
}
type MyData = WebSocketData | HttpStreamData
interface Header {
key: string;
val: string;
}
export interface WebSocketType {
url: string;
}
export interface HTTPStreamType {
url: string;
method: 'get' | 'put';
headers: Header[];
}
export class Stream {
constructor(
public _type: 'WEBSOCKET' | 'HTTP_STREAM',
public connection: WebSocketType | HTTPStreamType
) { }
}
let newStream = new Stream('WEBSOCKET', { url: 'myurl' })
let newStream2 = new Stream(
'HTTP_STREAM',
{ url: 'meaw', method: 'get', headers: [
{ key: 'someheader', val: 'somevalue' }
]
})
if (newStream._type === 'WEBSOCKET') {
if (newStream.connection.url.length > 0) {
//do stuff
}
}
if (newStream2._type === 'HTTP_STREAM') {
if (newStream2.connection.url.length > 0) {
//do stuff
}
}