typescript - 可选字段和联合字段有什么区别?

标签 typescript

以下之间有什么实际区别:

{
    ok: boolean;
} | {
    ok: boolean;
    error: any;
}

和:

{
    ok: boolean;
    error?: any;
}

我注意到前端方法返回值的推断类型的差异,两种方法都执行以下操作:

try {
  const response = await axios.post(url)
  return response.data as Payloads[Endpoints.EndpointName]
} catch (error) {
  return { ok: false, error }
}

其中一个 Payloads[Endpoints.EndpointName] 是:

{
    ok: boolean,
    error?: any,
}

另一个就是:

{
    ok: boolean,
}

我希望两个返回值的行为相同,但由于它们在形式上并不相同,我想知道我是否应该意识到一些怪癖。我能想到的唯一区别是联合类型允许使用排除(通常是联合的帮助程序)。还有什么吗?

最佳答案

TypeScript 不会让您索引 object type带有一个键,除非已知该键存在于该类型中。这在很大程度上是 {ok: boolean} | {ok: boolean, error: any} 之间可观察到的差异的原因。和{ok: boolean; error?: any} .

optional properties 之间通常还有进一步的差异以及所需的属性,涉及如何 undefined 已处理,但由于您的属性(property)类型是 the catch-all any type ,这种区别基本上消失了。


类型{ok: boolean}不知道有 error属性,因此如果您尝试使用 error 对其进行索引key,编译器会提示。这并不意味着 {ok: boolean} 类型的值不能拥有error属性(property); TypeScript 中的对象类型不是密封的(有关更多信息,请参阅 Typescript: prevent assignment of object with more properties than is specified in target interface)。因此,类型 {ok: boolean}其本身类似于 {ok: boolean; error?: any}已经。但使用未知的键对对象类型进行索引被认为是错误的。

此外,如果您有 union对于对象类型,您只能使用已知存在于联合的每个成员中的键对其进行索引。所以{ok: boolean} | {ok: boolean; error: any}仍然不允许您使用 error 对其进行索引关键,因为第一个工会成员不知道 error :

type T = { ok: boolean; } | { ok: boolean; error: any; }
declare const c: T;
c.error = {} // error  

另一方面,{ok: boolean; error?: any}确实知道 error属性,因此您可以对其进行索引。

type T = { ok: boolean; error?: any; }
declare const c: T;
c.error = {} // okay

IntelliSense 只会建议已知存在的键,因此您还会看到建议键中的差异。


此外,具有非联合属性的对象的联合在概念上类似于具有联合属性的非联合对象,但它们在 TypeScript 中不被视为等效。您的示例类型并不完全是这样,因为 any消除了区别,但很接近。比较 {a: string} | {a: number}{a: string | number} .

主要区别是联合体可以直接 narrowed通过各种类型保护,而非联合对象通常不会以这种方式缩小范围。

例如,如果您 assign联合类型变量的值,编译器会将该变量的表观类型缩小为仅相关联合成员。根据您分配的值,您可以在访问变量时获得不同的后续行为:

// union behavior
type T = { ok: boolean; } | { ok: boolean; error: any; }
const a: T = { ok: true }
a.error // error
const b: T = { ok: true, error: {} }
b.error // okay

// non-union behavior
type T = { ok: boolean; error?: any; }
const a: T = { ok: true }
a.error // okay
const b: T = { ok: true, error: {} }
b.error // okay

那么虽然a显示联合类型和非联合类型之间的相同区别,b在 union 情况下缩小为 {ok: boolean; error: any} ,因此突然之间的行为就像您使用非联合类型一样(它们之间的唯一区别是 error 在一个类型中是可选的,在另一个类型中是必需的,但这种区别并没有多大作用)。

Playground link to code

关于typescript - 可选字段和联合字段有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76897098/

相关文章:

javascript - ionic 选择 : pre selecte value is invisible until clicked once

angular - 当我使用 canActivate Guard 时,它会导致 Angular 4 中的空白页?

尽管设置了私有(private)属性,但 Typescript getter 返回 undefined

javascript - Angular 2+ : Internet Explorer: Unable to get property 'call' of undefined or null reference

javascript - Angular Firestore : Check if data exist and update a global variable based on that

javascript - 变量在分配之前使用(TypeScript)

Angular2 insideHtml 绑定(bind)破坏了数据绑定(bind)

typescript - 在 TypeScript 中对非类型化数据强制类型化

javascript - Vue3 - 如何避免 API 调用中的重复代码?

javascript - TestCafe错误: "No tests to run. Either the test files contain no tests or the filter function is too restrictive"