tom*_*ler 2 arrays instanceof typescript
我有一个接收数组的函数,但它们可以是不同的类型。根据我需要不同格式的类型:
public format(value: Foo[] | Bar[]) {
// this does not work
if (value instanceof Foo[]) ...
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以用来instanceof检查 Typescript 中是否有某个类的对象。
new Foo() instanceof Foo // true
Run Code Online (Sandbox Code Playgroud)
这也适用于检查我是否有数组。
new Array<Foo> instanceof Array // true
Run Code Online (Sandbox Code Playgroud)
但我无法检查我的数组是否实际上被输入到 Foo
new Array<Foo>() instanceof Array<Foo>
// The right-hand side of an 'instanceof' expression must be of type 'any'
// or of a type assignable to the 'Function' interface type.
Run Code Online (Sandbox Code Playgroud)
有没有办法显式检查数组值的类型?
Array<Foo>在运行时,和之间没有区别Array<Bar>;静态类型系统会从发出的 JavaScript 中删除,因此您拥有的只是一些 JavaScript 数组。因此,您需要编写自己的在运行时运行的测试,然后告诉编译器您在做什么,以便获得静态类型的好处。
一种方法是编写一些合适的用户定义类型保护函数,这可以让您执行此操作:
public format(value: Foo[] | Bar[]) {
const isFooArray = isArrayOf(isInstanceOf(Foo));
if (isFooArray(value)) {
// true block
for (const foo of value) {
const f: Foo = foo; // okay
}
} else {
// false block
for (const bar of value) {
const b: Bar = bar; // okay
}
}
}
Run Code Online (Sandbox Code Playgroud)
编译器知道,在 true 块内,value已从 缩小到Foo[] | Bar[]just Foo[],而在 false 块内,value已从 缩小到Foo[] | Bar[]just Bar[]。这与 的类型签名有关isFooArray(),它是通过组合其他两个函数isArrayOf()和的输出创建的类型保护isInstanceOf()。
让我们检查一下它们的定义:
const isArrayOf = <T>(elemGuard: (x: any) => x is T) =>
(arr: any[]): arr is Array<T> => arr.every(elemGuard);
Run Code Online (Sandbox Code Playgroud)
该函数采用单个数组元素的isArrayOf()类型保护函数,并返回一个调用数组的每个元素的新类型保护。如果所有元素都通过测试,那么您就有了一个受保护类型的数组。如果甚至有一个元素没有通过,那么你就没有通过。如果您愿意,您可以只检查一个元素,但是您可能会冒着意外将异构数组(如. 另请注意,这意味着空数组始终会通过测试;因此空数组将被视为 a和a 。elemGuardelemGuardArray<Foo | Bar>Foo[][]Foo[] Bar[]
const isInstanceOf = <T>(ctor: new (...args: any) => T) =>
(x: any): x is T => x instanceof ctor;
Run Code Online (Sandbox Code Playgroud)
该isInstanceOf()函数只是将正常instanceof测试包装到适合与isArrayOf().
复合类型保护也是如此,它通过检查每个元素并进行检查const isFooArray = isArrayOf(isInstanceOf(Foo))来专门检查它正在检查的数组是否是 a 。Foo[]instanceof
好的,希望有帮助;祝你好运!