【发布时间】:2020-04-04 09:09:27
【问题描述】:
我想将类型定义为显式属性和泛型类型的混合,在匹配键的情况下显式属性优先。以下是我的尝试,但在指示的行上出现错误 - 谁能解释为什么或者这是一个 tsc/编译器错误?
// Takes properties in A and B. For matching properties, the types in A are used.
type Mix<A, B> = {
[K in keyof B | keyof A]: K extends keyof A
? A[K]
: K extends keyof B
? B[K]
: never
}
type Versionable = { version: number }
function test<T>(): void {
const version1: Partial<Mix<Versionable, T>>['version'] = 1 // compiles - version type is correctly inferred as number | undefined
const version2: Partial<Mix<Versionable, T>>['version'] = undefined // compiles
const version3: Partial<Mix<Versionable, T>>['version'] = '1' // does not compile as expected
const obj1: Partial<Mix<Versionable, T>> = { version: 1 } // DOES NOT COMPILE.... WHY??
const obj2: Partial<Mix<Versionable, T>> = { version: undefined } // compiles
const obj3: Partial<Mix<Versionable, T>> = { version: '1' } // does not compile as expected
const obj4: Partial<Mix<Versionable, T>> = {} // compiles
obj4.version = 1 // compiles
}
【问题讨论】:
-
非常有趣。看起来问题出在泛型 T 上,因为一切都适用于静态类型集。首先想到的是,如果 B 未知,则问题可能在于 A 和 B 之间的交叉点,编译器无法解决此问题。尝试过这种类型,现在没有运气:
type Mix<A, B> = { [K in keyof A]: A[K] } & { [K in Exclude<keyof B, keyof A>]: B[K] } -
问题是这样的结构有什么意义,因为我们知道你不能在
test函数的主体中放置T的任何属性,因为在这个级别是未知的。这意味着此函数始终仅适用于Partial<Versionable>类型。你能在这里分享一下 type T 的目的是什么吗? -
同一类型的另一个版本是 -
type Mix<A, B> = A & Pick<B, Exclude<keyof B, keyof A>>。但问题仍然是test中类型 T 的目的 -
嗨,简而言之,我有一个使用泛型 T 参数化的 API,但它对 T 有某些要求,例如可版本化。但是 T extends { version: number } 例如不会削减它,因为我不能在指定 filter/where 子句时做 T 的一部分并将其设置为 { version: 1 } 。 (因为在 T 版本中可能会扩展为比数字更具体的类型,只说数字 2 和 3,因此编译器不会让我将其设置为 1)。因此,除了我需要的属性外,我需要一个全是 T 的类型。希望这是有道理的!
标签: typescript typescript-generics