如何使用 Typescript 检查数组中泛型的实例
How to check instance of the generic in Array with Typescript
我有一个接收数组的函数,但它们可以是不同类型的。根据我需要不同格式的类型:
public format(value: Foo[] | Bar[]) {
// this does not work
if (value instanceof Foo[]) ...
}
我知道我可以使用 instanceof
检查 Typescript 中是否有某个 class 的对象。
new Foo() instanceof Foo // true
这也适用于检查我是否有数组。
new Array<Foo> instanceof Array // true
但我无法检查我的数组是否真的输入了 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.
有什么方法可以显式检查数组值的类型吗?
您需要检索一个项目并检查该项目的类型。但是因为 TypeScript 有静态类型,数组的对象总是来自 Foo 类型。
在运行时Array<Foo>
和Array<Bar>
没有区别;静态类型系统是 erased 来自发出的 JavaScript,所以你所拥有的只是一些 JavaScript 数组。因此,您需要编写自己的在 运行 时间运行的测试,然后告诉编译器您在做什么,以便获得静态类型的好处。
一种方法是编写一些合适的 user-defined type guard functions,这样你就可以这样做:
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
}
}
}
编译器理解在 true 块内,value
已从 Foo[] | Bar[]
缩小到 Foo[]
,而在 false 块内,value
已缩小从 Foo[] | Bar[]
缩小到 Bar[]
。这与 isFooArray()
的类型签名有关,它是通过组合其他两个函数 isArrayOf()
和 isInstanceOf()
.
的输出创建的类型保护
让我们检查一下它们的定义:
const isArrayOf = <T>(elemGuard: (x: any) => x is T) =>
(arr: any[]): arr is Array<T> => arr.every(elemGuard);
函数 isArrayOf()
为单个数组元素采用类型保护函数 elemGuard
和 returns 对数组的每个元素调用 elemGuard
的新类型保护.如果所有元素都通过了测试,那么你就有了一个受保护类型的数组。如果连一个元素都没有通过,那么你就没有通过。如果你愿意,你可以只检查一个元素,但是你 运行 不小心将 Array<Foo | Bar>
之类的异构数组视为 Foo[]
的风险。另请注意,这意味着空数组 []
将始终通过测试;所以一个空数组将被认为是 Foo[]
和 和 Bar[]
.
const isInstanceOf = <T>(ctor: new (...args: any) => T) =>
(x: any): x is T => x instanceof ctor;
isInstanceOf()
函数只是将正常的 instanceof
测试包装到适合与 isArrayOf()
一起使用的用户定义类型保护中。
所以 const isFooArray = isArrayOf(isInstanceOf(Foo))
是一个复合类型保护,它通过检查每个元素并进行 instanceof
检查来专门检查它正在检查的数组是否是 Foo[]
。
好的,希望对您有所帮助;祝你好运!
我有一个接收数组的函数,但它们可以是不同类型的。根据我需要不同格式的类型:
public format(value: Foo[] | Bar[]) {
// this does not work
if (value instanceof Foo[]) ...
}
我知道我可以使用 instanceof
检查 Typescript 中是否有某个 class 的对象。
new Foo() instanceof Foo // true
这也适用于检查我是否有数组。
new Array<Foo> instanceof Array // true
但我无法检查我的数组是否真的输入了 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.
有什么方法可以显式检查数组值的类型吗?
您需要检索一个项目并检查该项目的类型。但是因为 TypeScript 有静态类型,数组的对象总是来自 Foo 类型。
在运行时Array<Foo>
和Array<Bar>
没有区别;静态类型系统是 erased 来自发出的 JavaScript,所以你所拥有的只是一些 JavaScript 数组。因此,您需要编写自己的在 运行 时间运行的测试,然后告诉编译器您在做什么,以便获得静态类型的好处。
一种方法是编写一些合适的 user-defined type guard functions,这样你就可以这样做:
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
}
}
}
编译器理解在 true 块内,value
已从 Foo[] | Bar[]
缩小到 Foo[]
,而在 false 块内,value
已缩小从 Foo[] | Bar[]
缩小到 Bar[]
。这与 isFooArray()
的类型签名有关,它是通过组合其他两个函数 isArrayOf()
和 isInstanceOf()
.
让我们检查一下它们的定义:
const isArrayOf = <T>(elemGuard: (x: any) => x is T) =>
(arr: any[]): arr is Array<T> => arr.every(elemGuard);
函数 isArrayOf()
为单个数组元素采用类型保护函数 elemGuard
和 returns 对数组的每个元素调用 elemGuard
的新类型保护.如果所有元素都通过了测试,那么你就有了一个受保护类型的数组。如果连一个元素都没有通过,那么你就没有通过。如果你愿意,你可以只检查一个元素,但是你 运行 不小心将 Array<Foo | Bar>
之类的异构数组视为 Foo[]
的风险。另请注意,这意味着空数组 []
将始终通过测试;所以一个空数组将被认为是 Foo[]
和 和 Bar[]
.
const isInstanceOf = <T>(ctor: new (...args: any) => T) =>
(x: any): x is T => x instanceof ctor;
isInstanceOf()
函数只是将正常的 instanceof
测试包装到适合与 isArrayOf()
一起使用的用户定义类型保护中。
所以 const isFooArray = isArrayOf(isInstanceOf(Foo))
是一个复合类型保护,它通过检查每个元素并进行 instanceof
检查来专门检查它正在检查的数组是否是 Foo[]
。
好的,希望对您有所帮助;祝你好运!