Reputation: 203
If I have a type like
export interface MyObject {
id: number
title: string
}
and I create an array like this
const myArray: MyObject[] = [
{
id: 2358,
title: 'Item 1'
},
{
id: 85373,
title: 'Item 2'
}
]
Is there a way to define a type that only allows values that have appeared as an id in the array? So in this case it would look like.
type DesiredType = 2358 | 85373
Here is a link to a Codewich where I have tried a few things to no avail.
Upvotes: 0
Views: 1904
Reputation: 3391
You can define a new type that has the type of the id
property using, for example, Pick
:
type MyObjectIdType = Pick<typeof myArray[number], 'id'>;
The problem here is that the array is a dynamic value and the compiler will infer the type as the most generic one, i.e., number
. To have the compiler use the actual values of the id
property you must tell it that the array is, in fact, a compile-time constant:
const myArray = [
{
id: 2358,
title: 'Item 1'
},
{
id: 85373,
title: 'Item 2'
}
] as const;
Note that for this to work I had to remove the type declaration MyObject[]
from myArray
, because a generic array of MyObject
it is not compatible with the constant declaration (it may have more or less than 2 elements, with id
s different from the given ones).
Obviously, this means that if you want to operate on a dynamic array, generated at runtime (and I expect you'd want), this will not work.
Upvotes: 1
Reputation: 249536
To get the type of id
in myArray
you can use a type query: typeof myArray[number]['id']
. The problem is that the type of id
is not preserverd in the type of myArray
.
To preserve the type you can use as const
(but you loose the MyObject constraint)
const myArray = [
{
id: 2358,
title: 'Item 1'
},
{
id: 85373,
title: 'Item 2'
}
] as const;
type Id = typeof myArray[number]['id']
Or you can use a helper function:
function makeMyObjectArray<V extends number>(...a: Array<MyObject & { id: V}>) {
return a;
}
const myArray = makeMyObjectArray(
{
id: 2358,
title: 'Item 1'
},
{
id: 85373,
title: 'Item 2'
}
)
type Id = typeof myArray[number]['id']
Upvotes: 3