下面给出getWrapper
中的编译错误:
type Wrapper<K> = {
value: K
}
type Wrappers = {
[K in 'henk' | 'piet']: Wrapper<K>
}
const wrappers: Wrappers = {
'henk': { value: 'henk' },
'piet': { value: 'piet' }
}
function getWrapper<K extends keyof Wrappers>(k: K): Wrapper<K> {
return wrappers[k]
}
它说dat
wrappers[k]
就是Wrapper<'henk'> | Wrapper<'piet'>
。它应该能够计算出wrappers[k]
实际上是Wrapper<K>
。我能帮typescript解决这个问题吗? 最佳答案
更新:2019-05-30版本3.5的版本介绍了smarter union type checking但它没有解决这个问题,可能是因为它使用了一个泛型类型K
而不是一个已知的具体类型的联盟。所以到现在为止,下面的解决方案没有变化。
我很确定你的问题是“AA>你期望的方式。”例如,您可能希望以下操作有效:
declare const innerUnion: { foo: string | number };
const outerUnion: { foo: string } | { foo: number } = iU; // error
但它没有。typescript没有积极地将
outerUnion
的类型减少到innerUnion
的类型。编译器不自动执行此操作的原因似乎是实用主义:在许多情况下,这样的缩减是错误的,因为有另一个属性无法合并:declare const iU: { foo: string | number, bar: string | number };
const oU: { foo: string, bar: string } | { foo: number, bar: string } = iU; // error
上面的错误是一个很好的错误,因为
iU
可能是{ foo: 0, bar: '' }
。typescript认为
K
可以是'henk' | 'piet'
类型,因此函数的输出可以是Wrapper<'henk' | 'piet'>
,但返回值是Wrapper<'henk'> | Wrapper<'piet'>
类型。由于上面的联合缩减是typescript做不到的,所以它说有一个错误。那么,为什么返回值的类型是
Wrapper<'henk'> | Wrapper<'piet'>
?因为用键的联合对对象进行索引确实会导致该对象的属性值的合并。这意味着要解决问题,使用TypeScript doesn't reduce unions来表示索引操作:
function getWrapper<K extends keyof Wrappers>(k: K): Wrappers[K] {
return wrappers[k]; // okay
}
我想这是你想要的。希望有帮助,祝你好运!
关于typescript - typescript :类型系统无法证明似乎是正确的东西,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47926868/