Typescript 泛型类型的部分类型脚本

Typescript 泛型类型的部分类型脚本,typescript,typescript-generics,Typescript,Typescript Generics,我想将类型定义为显式属性和泛型类型的混合,在匹配键的情况下显式属性优先。下面是我的尝试,但我在指示的行上得到了一个错误-有人能解释为什么或者这是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]

我想将类型定义为显式属性和泛型类型的混合,在匹配键的情况下显式属性优先。下面是我的尝试,但我在指示的行上得到了一个错误-有人能解释为什么或者这是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
}
//获取A和B中的属性。要匹配属性,请使用A中的类型。
类型组合={
[K in keyof B | keyof A]:K扩展了A的keyof
?A[K]
:K/B
?B[K]
:从不
}
类型Versionable={version:number}
函数测试():void{
const version1:Partial['version']=1//编译-版本类型正确推断为数字|未定义
const version2:Partial['version']=未定义//编译
const version3:Partial['version']='1'//未按预期编译
const obj1:Partial={version:1}//未编译…为什么??
常量obj2:Partial={version:undefined}//编译
const obj3:Partial={version:'1'}//未按预期编译
const obj4:Partial={}//编译
obj4.version=1//编译
}

我认为这里的行为与中相同;编译器几乎不会将任何具体值视为可分配给
Partial
,但属性类型为
undefined
(这负责
obj2
的行为)或空对象(这负责
obj4
的行为)的值除外

这种限制通常是合理的,因为这些分配通常是不安全的:

function unsafeCaught<T extends { a: string }>() {
  const nope: Partial<T> = { a: "" }; // CORRECT error  
}
interface Oops { a: "someStringLiteralType" };
unsafeCaught<Oops>(); // {a: ""} is not a valid Partial<Oops>
(这负责
obj1
的行为。)在这些情况下,编译器根本不执行使其工作所需的分析。A实际上被认为是一个bug并已修复,但在这种情况下,映射的属性类型是一个常量,如
number
,而在您的属性类型中,它是一个条件类型。编译器在验证依赖于未解析泛型参数的条件类型的可分配性方面已经做得相当糟糕。因此,对于您的情况,我将其归结为TypeScript的设计限制,并使用a来确定您在这种情况下比编译器更了解:

const obj1 = { version: 1 } as Partial<Mix<Versionable, T>>; // okay now
const obj1={version:1}作为部分;//好了

奇怪的是,当您写入属性而不是将对象指定给变量时,此限制会被放宽,因此最终会出现完全相同的错误行为:

function unsafeUncaught<T extends { a: string }>(val: Partial<T>) {
  val.a = ""; // uh, wait
}
const oops: Oops = { a: "someStringLiteralType" };
unsafeUncaught(oops);
函数unsafeUncaught(val:Partial){
val.a=“”;//嗯,等等
}
常量oops:oops={a:“someStringLiteralType”};
未封包(oops);
我很抱歉,但这可能是某个地方的设计决定。因此,以下内容也没有给出任何错误,但只是巧合,因为它首先没有正确检查:

function safeUncaught<T extends { a: string }>(
  val: { [K in keyof T]?: K extends "a" ? string : T[K] }
) {
  val.a = ""; // okay but coincidentally
}
功能安全未捕获(
val:{[K in keyof T]?:K扩展了“a”?字符串:T[K]}
) {
val.a=“”;//好吧,但巧合的是
}
这可能就是您的
version1
version2
version3
以及
obj4.version=1
工作的原因


好的,希望能有帮助。祝你好运


非常有趣。看起来问题出在泛型T上,因为每次对静态类型集都有效。第一个想法是,问题可能是A和B之间的交集,如果B未知,编译器无法解决这个问题。尝试过这样的类型,但现在没有运气:
type Mix={[K in keyof A]:A[K]}&{[K in Exclude]:B[K]}
问题是什么意义上有这样的结构,正如我们所知,您不能在
test
函数体中放置T的任何属性,因为在这个级别上它是未知的。这意味着此函数始终仅适用于
Partial
类型。你能在这里分享类型T的用途吗?相同类型的另一个版本是-
typemix=A&Pick
。但是仍然存在的问题是T型在
test
Hi中的用途,简言之,我有一个用泛型T参数化的API,但它对T有某些要求,比如可版本性。但是T扩展{version:number}不会剪切它,因为在指定一个filter/where子句时,我不能对T进行部分操作并将其设置为{version:1}。(因为在T版本中,可能会被扩展为比数字更具体的类型,只说数字2和3,因此编译器不允许我将其设置为1)。因此,我需要一个类型,除了我需要的属性之外,它都是T。希望这有意义!谢谢你。我将把它记为一个编译器错误,然后向我的小朋友问好。。。。任何!;)
function safeUncaught<T extends { a: string }>(
  val: { [K in keyof T]?: K extends "a" ? string : T[K] }
) {
  val.a = ""; // okay but coincidentally
}