Typescript - 缩小函数返回类型的类型联合范围
为什么 Typescript 无法区分其类型来自函数返回类型的类型联合,而无需在函数上显式声明返回类型?
这里我没有指定事件创建函数的返回值,并且联合类型不能缩小。
enum EventType {
FOO = "foo",
GOO = "goo",
}
function createFooEvent(args: {
documentId: number | null
}) {
return {
type: EventType.FOO,
data: args
}
}
function createGooEvent(args: {
id: number
isSelected: boolean
}) {
return {
type: EventType.GOO,
data: args
}
}
type EventArgType =
| ReturnType<typeof createFooEvent>
| ReturnType<typeof createGooEvent>
function eventHandler(event: EventArgType) {
switch(event.type) {
case EventType.FOO: {
// Note that `event` contains `data` but `data`'s type is a union and has not been discriminated
event.data;
break
}
}
}
但是,如果我按如下方式指定返回类型,则可以区分联合。
function createFooEvent(args: {
documentId: number | null
}): {
type: EventType.FOO,
data: {
documentId: number | null
}} {
return {
type: EventType.FOO,
data: args
}
}
function createGooEvent(args: {
id: number
isSelected: boolean
}): {
type: EventType.GOO,
data: {
id: number
isSelected: boolean
}} {
return {
type: EventType.GOO,
data: args
}
}
<一href="https://www.typescriptlang.org/play?#code/PTAEDkHlwWgdUgJQNIElwHFQFgBQeAzAVwDsBjAFwEsB7E0AUwA8BDAWwAcAbByEhgBQBKAN55QjEkTagAogDcGJCgBUAnhwagx uCRIBikSKAC8oAEQEaNcwBpxejEdMWA5tbsOAvngfFy1HSgZABODCwUDPrWCkoUAiwhrgDOAFzaDhiAJjRk0nGoWelSbABGDCGgAD6gUlxc3kIZunphFEQh9Dp6ehQaDOmxyuqaAHSGkPYtPVkR LOmJKZmgPi2rEv6UtPSh4ZEYMYrKCUlpzT1URbXS5SHLVMkAygw8lAxXpdY8LCSN560Mdqdf4 9PqaQZHVT9UZOSbLbJzBanZbrFa+FpgrRDCgAQSSIy0JmWNUQgI6JAJAB5MTQCMEwhEooc4gA+ YmgULAin9an9Wn0vYMA40bFs-AtTaBegMSEACR+WR4IQEMriELieNcBKa3T0yQA7lQKGQABYqyGjTE6+HBFjJLGQgnjIzpXU9CQgCA0SKgCgmiKgAAGquUgeCdAoLCoJGSQdmkbDpSIFDjc0DAH JY5jQA9QCxQKRtnmSFlQP7YyRvaBykpQFkHqEqGxo4ysjaJCGKKN4ywanzt6sMgDWNtRELRq1 WeE9CBQj3RkqLzHY3AYKn1NGE-yU0jkjv6INAExclg8Ux6sJP7hs57R4o9YHA3q0foDfq0bXJv v6sf57-taoRDQlSLnQsa5sw3BUGQRplhUWjyFmJpaMunA8HmnyKH4pBbEuyMtEIqQicKSuss OR5GwBRXCUtzVNc9SNGR0zfuCe5xE6Ey3gikbMe6da5PkyiFMUNwVPRdQNGsXiHp+wJur0-Tqs M0JcTaPZIksLETthARFvh+zMscixnAplyiWUFT3E8LwMG8HxfOEvxrEIfGKWx2JOrC3F1oih4SOZ1yWXcLEBTZryRA5NDfM544yQpcldDamLKVCYzeepfkmSi3johI2bYpqBKmOynLklSNJ0gZT JEaypVkp0FV8lVDKGbVyhirpuHSnKCpKuaarscoRX9NaLEGkapoDcolqjf5toAZ5qkuvND5ej 6r4psGkJhmQEZRjGqYJsWpaBj2GZZge5bVgwtb1skjbNiQrYDp23ZzP2oV6KUw6jjlax4KsQA" rel="nofollow noreferrer">这是 TS Playground 中的示例。
Why is it that Typescript cannot discriminate a type union whose types are from the return types of function, without explicitly declaring the return type on the function?
Here I do not specify the return values of the event creator functions and the union type cannot be narrowed.
enum EventType {
FOO = "foo",
GOO = "goo",
}
function createFooEvent(args: {
documentId: number | null
}) {
return {
type: EventType.FOO,
data: args
}
}
function createGooEvent(args: {
id: number
isSelected: boolean
}) {
return {
type: EventType.GOO,
data: args
}
}
type EventArgType =
| ReturnType<typeof createFooEvent>
| ReturnType<typeof createGooEvent>
function eventHandler(event: EventArgType) {
switch(event.type) {
case EventType.FOO: {
// Note that `event` contains `data` but `data`'s type is a union and has not been discriminated
event.data;
break
}
}
}
But if I specify the return types as follows then the union can be discriminated.
function createFooEvent(args: {
documentId: number | null
}): {
type: EventType.FOO,
data: {
documentId: number | null
}} {
return {
type: EventType.FOO,
data: args
}
}
function createGooEvent(args: {
id: number
isSelected: boolean
}): {
type: EventType.GOO,
data: {
id: number
isSelected: boolean
}} {
return {
type: EventType.GOO,
data: args
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因为默认情况下,typescript 不会将常量推断为类型: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions
例如:
Typescript 将推断类型
a
作为string
而不是'test'
。您可以使用
as const
修复它:在这种情况下,
a
的类型将为'test'
。您的代码也是如此:
函数的返回类型是
{type: EventType}
而不是{type:'foo'}
。将
as const
添加到返回类型,将按照您的预期工作TS 游乐场Because typescript does not infer the constant as the type by default: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions
For example:
Typescript will infer type of
a
asstring
not as'test'
.You can fix it using
as const
:In this case
a
will be of type'test'
.Same for your code:
The return type of the function is
{type: EventType}
instead of{type:'foo'}
.Adding
as const
to the return type, will work as you expect TS Playground