typescript - 如何在打字稿中打开泛型对象的属性?
问题描述
我有一个属性类型是通用的类型。
我想打开属性来推断泛型值的类型。
这是我为实现这一目标所做的代码。我认为这会起作用,因为编译器应该具有推断类型所需的所有信息。显然不是,因为编译器会抛出错误。
type Foo<T> = {
value: T
}
type A = { type: 'a', data: number }
type B = { type: 'b', data: string }
type AB = A | B
function doStuff(foo: Foo<AB>) {
switch(foo.value.type) {
case 'a': {
// here TS knows that foo.value is an `A`, why isnt foo a Foo<A> ?
return doStuffA(foo) // Error (1) on foo
}
case 'b': {
return doStuffB(foo) // Error(2) also on foo
}
}
}
function doStuffA(foo: Foo<A>) {
// ...
}
function doStuffB(foo: Foo<B>) {
// ...
}
和错误:
(Error 1)
Argument of type 'Foo<AB>' is not assignable to parameter of type 'Foo<A>'.
Type 'AB' is not assignable to type 'A'.
Type 'B' is not assignable to type 'A'.
Types of property 'type' are incompatible.
Type '"b"' is not assignable to type '"a"'.
(Error 2)
Argument of type 'Foo<AB>' is not assignable to parameter of type 'Foo<B>'.
Type 'AB' is not assignable to type 'B'.
Type 'A' is not assignable to type 'B'.
Types of property 'type' are incompatible.
Type '"a"' is not assignable to type '"b"'.
这是 Typescript 的限制吗?或者我做错了什么?
解决方案
感谢评论中的 Ben Wainwright,我找到了解决方案。
我需要创建改进类型的函数Foo<T>
。
type Foo<T> = {
value: T
}
type A = { type: 'a', data: number }
type B = { type: 'b', data: string }
type AB = A | B
// here, isA tells the TS compiler that foo is indeed a Foo<A>
function isA(foo: Foo<AB>): foo is Foo<A> {
return foo.value.type === 'a'
}
// same here for Foo<B>
function isB(foo: Foo<AB>): foo is Foo<B> {
return foo.value.type === 'b'
}
function doStuff(foo: Foo<AB>) {
if(isA(foo)) {
// it works ! here TS recognise foo as Foo<A>
return doStuffA(foo)
} else if(isB(foo)) {
// same here, TS knows that foo is a Foo<B>
return doStuffB(foo)
}
}
function doStuffA(foo: Foo<A>) {
// ...
}
function doStuffB(foo: Foo<B>) {
// ...
}
推荐阅读
- symfony - 检测到服务“kernel.listener.your_listener_name”的循环引用,
- python - 如何在序列中分离最长的重复字符模式,其中每个模式可以被未知数量的字符分隔?
- html - 如何根据下拉值进行路由?
- html - 在标签内设置图像样式
- javascript - 停止内部锚标记函数调用外部输入字段函数javascript
- python - 使用日期时间索引切片数据帧
- regex - 如何仅匹配和标记两个单词,但它们之间有一个字符串?
- hololens - 如何让媒体投射在 HoloLens 1 上工作
- android - Firestore 在上一个任务未完成之前不会加载数据。无法设置加载优先级
- python - 需要更好的套接字超时条件