I want to write a typeguard to check if all children of array are of type T thus making it an Array where T is a generic type
// Assume arr of any type but Array
const arr: any[] = [
{
foo: "bleh1",
bar: 1
},
{
foo: "bleh2",
bar: 2
},
]
interface newType {
foo: string
bar: number
}
// Check that arr is an array of newType , ie arr: newType[]
const isArrayOf = <T,>(arr: any): arr is Array<T> => {
// TypeScript mastery needed here
return true
}
if(isArrayOf<newType>(arr)){
arr
}
CodePudding user response:
The best thing you could do is this:
const arr: NewType[] = [
{
foo: "bleh1",
bar: 1
},
{
foo: "bleh2",
bar: 2
},
]
interface NewType {
foo: string
bar: number
}
type TypeOfArrayElements<T> = T extends Array<infer U> ? U : never;
type ArrayType = TypeOfArrayElements<typeof arr>;
TypeScript will never be able to guess that the array typed as any[]
actually contains NewType
elements. Like everything in TypeScript, type predicates are static and won't return a type dynamically based on what is passed as a parameter at runtime. But if you type it as NewType[]
, then you can extract the NewType
type from it.
CodePudding user response:
This can be incorrect , needs review
If an array a
is of type newType[]
then every element of a , consider x = a[0]
will be of type newType
. x
is of type newType
because x
satisfies all properties and methods of type newType
.
Thus if reversed , if x
y
z
are of type newType
and they are the only and all elements of array a
, Thus every element of a
are of type newType
, which satisfies the condition for a
to be of type newType[]
// Check if obj has all keys props[]
const hasAllProperties = <T,>(obj: any, props: (keyof T)[]): obj is T => {
return props.every((prop) => {
// console.log(prop)
return Object.prototype.hasOwnProperty.call(obj, prop)})
}
// Check that arr is an array of newType , ie arr: newType[]
const isArrayOf = <T,>(obj: any[], props: (keyof T)[]): obj is T[] => {
// Check if every elements have all keys in props
return obj.every((ele) => {
// console.log(ele)
return hasAllProperties<T>(ele,props)
}
)
}
if (isArrayOf<newType>(arr, ["foo", "bar"])) {
console.log("arr is of newType[]")
}