dea*_*mon 5 typescript spread-expression
我使用展开运算符来创建具有更改字段的副本,如以下示例 ( run ) 所示。但是,如果在创建对象文字时更改字段的类型,编译器不会抱怨:
class A{
constructor(readonly a: number, readonly b: string[]){}
copy(): A { // must return an object of type A
return {
...this,
b: 99 // should be of type string[]!
}
}
}
const a: A = new A(1, ["x", "y"])
const a1 = a.copy()
console.log(JSON.stringify(a1))
Run Code Online (Sandbox Code Playgroud)
输出:
[LOG]: "{"a":1,"b":99}"
Run Code Online (Sandbox Code Playgroud)
创建显式接口也没有帮助:
interface IA {
readonly a: number
readonly b: string[]
}
...
copy(): IA { ...
Run Code Online (Sandbox Code Playgroud)
看起来它与数组无关,因为下一个示例也可以编译:
class A{
constructor(readonly a: number, readonly b: number){}
copy(): A {
return {
...this,
b: "my string" // should be of type number!
}
}
}
Run Code Online (Sandbox Code Playgroud)
为什么这在 TypeScript 中是可能的?或者这是一个编译器错误?有没有办法避免
这是以下类型系统事实之间的交互:
this确实是多态类型this。多态this是扩展当前类的类的隐式泛型类型参数。(参考见最后一段)A & B可以分配给两者A,并且无论和B的任何属性之间是否存在任何不兼容性(示例)(参考参见分配兼容性)AB{ ...this, b: 99 }在这里应用这 3 个规则,我们得到as的类型this & { b: number }(证明)。哪个 可以分配给A自从this extends A。
例如,如果您输入 assert thisto A,您实际上会收到错误,因为不涉及通用操作数的扩展操作被正确输入(ex)
至于这是否是一个错误,我将其称为设计限制。很长一段时间以来,将扩展与通用类型操作数一起使用是不可能的。这个功能是在 3.2 ( PR )中添加的,阅读 PR 中的注释我们可以清楚地看到团队已经意识到这里的一些漏洞:
{ ...T, ...U }使用交集的替代方法是按照#10727探索的内容引入高阶类型运算符。虽然这乍一看很有吸引力,但实现这个新类型构造函数并赋予它我们已经为交集类型实现的所有功能需要大量工作,并且在大多数情况下它只会产生很少或没有精度增益。特别是,只有当扩展表达式涉及具有不同类型的重叠属性名称的对象时,差异才真正重要。此外,对于不受约束的类型参数T,该类型{ ...T, ...T }实际上无法分配给T,这虽然在技术上是正确的,但在学究气上会很烦人。
添加了上面的重点,您的用例正好属于这个问题。
| 归档时间: |
|
| 查看次数: |
1718 次 |
| 最近记录: |