为什么这个多态赋值在 Knockout 中的类型化 observableArray 中不起作用?
Why this polymorphic assignment does not work in typed observableArray in Knockout?
让我们有 class A
和 subclass B
。我想将 B
的数组分配给 A
的数组。对于普通数组,它按预期工作,但对于 ko.ObservableArray
它失败了。
import ko from "knockout";
class A {};
class B extends A {b = 1};
const a: A = new B(); // no problem here
const aArr: A[] = [] as B[]; // no problem here
// COMPILER PROBLEM ON LAST LINE!
const aObs: ko.ObservableArray<A> = ko.observableArray() as ko.ObservableArray<B>;
编译器对最后一行不满意,显示此错误:
Type 'ObservableArray<B>' is not assignable to type 'ObservableArray<A>'.
Types of parameters 'value' and 'value' are incompatible.
Type 'A[] | null | undefined' is not assignable to type 'B[] | null | undefined'.
Type 'A[]' is not assignable to type 'B[]'.
Type 'A' is not assignable to type 'B'.
但显然我不想将 A
分配给 B
,而是 B
分配给 A
。
如何应对?
问题是 ObservableArray<T>
is contravariant 它的类型变量 T
。这就是它尝试反向分配类型的原因。
虽然您可以自由地将 B
分配给 A
(因为 B extends A
并且您甚至不必将其声明为 extends
)当它进入协变时位置:
class A { }
class B { b = 1 }
const a: A = new B();
const aArr: A[] = [] as B[];
您不能在同一方向上分配接受这些类型参数的函数。只在对面。
type Fn<T> = (t: T) => void
const fn1: Fn<A> = null as unknown as Fn<B> // error here
const fn2: Fn<B> = null as unknown as Fn<A> // no error
以防万一您绝对确定赋值完全正确并且编译器不必要地限制您。您可以自行承担责任并将其转换为预期类型:
import ko, { ObservableArray } from 'knockout'
class A {};
class B extends A {b = 1};
const bObs: ObservableArray<B> = ko.observableArray()
const aObs: ObservableArray<A> = bObs as unknown as ObservableArray<A>;
您还可以使用 --strictFunctionTypes
选项全局关闭 fn 参数的逆变检查。虽然大多数时候这是非常有用的检查。
让我们有 class A
和 subclass B
。我想将 B
的数组分配给 A
的数组。对于普通数组,它按预期工作,但对于 ko.ObservableArray
它失败了。
import ko from "knockout";
class A {};
class B extends A {b = 1};
const a: A = new B(); // no problem here
const aArr: A[] = [] as B[]; // no problem here
// COMPILER PROBLEM ON LAST LINE!
const aObs: ko.ObservableArray<A> = ko.observableArray() as ko.ObservableArray<B>;
编译器对最后一行不满意,显示此错误:
Type 'ObservableArray<B>' is not assignable to type 'ObservableArray<A>'.
Types of parameters 'value' and 'value' are incompatible.
Type 'A[] | null | undefined' is not assignable to type 'B[] | null | undefined'.
Type 'A[]' is not assignable to type 'B[]'.
Type 'A' is not assignable to type 'B'.
但显然我不想将 A
分配给 B
,而是 B
分配给 A
。
如何应对?
问题是 ObservableArray<T>
is contravariant 它的类型变量 T
。这就是它尝试反向分配类型的原因。
虽然您可以自由地将 B
分配给 A
(因为 B extends A
并且您甚至不必将其声明为 extends
)当它进入协变时位置:
class A { }
class B { b = 1 }
const a: A = new B();
const aArr: A[] = [] as B[];
您不能在同一方向上分配接受这些类型参数的函数。只在对面。
type Fn<T> = (t: T) => void
const fn1: Fn<A> = null as unknown as Fn<B> // error here
const fn2: Fn<B> = null as unknown as Fn<A> // no error
以防万一您绝对确定赋值完全正确并且编译器不必要地限制您。您可以自行承担责任并将其转换为预期类型:
import ko, { ObservableArray } from 'knockout'
class A {};
class B extends A {b = 1};
const bObs: ObservableArray<B> = ko.observableArray()
const aObs: ObservableArray<A> = bObs as unknown as ObservableArray<A>;
您还可以使用 --strictFunctionTypes
选项全局关闭 fn 参数的逆变检查。虽然大多数时候这是非常有用的检查。