Reputation: 491
I am trying to add a new array item to the start of an existing array and get an error. I am trying to add a new array item to the array that is constructed on the fly. The example code below causes an error using the unshift operation.
The array that I want to insert to is lRtn.document.mainTemplate.item.item
s and I am using lodash to iterate over the parameter _pUrls
and for each url
I am creating a new array item and want to push the new array item to the existing array lRtn.document.mainTemplate.item.items
leaving the existing array content in place.
The error is get is
Argument of type '{ type: string; description: string; source: any; }' is not assignable to parameter of type '{ type: string; duration: number; contentType?: undefined; content?: undefined; } | { type: string; contentType: string; content: string; duration?: undefined; }'.
Type '{ type: string; description: string; source: any; }' is missing the following properties from type '{ type: string; contentType: string; content: string; duration?: undefined; }': contentType, content
The code that I have tried is here below, any help or guidance would be much appreciated.
export async function createAPLADirectiveBookReviews(
_pUrls: any,
_pFollowOn: string,
) {
const lDescription = 'review';
const lRtn = {
type: constants.APLA.directiveType,
token: constants.APLA.token,
document: {
version: '0.91',
type: 'APLA',
description: 'This document demonstrates key components used to create audio responses.',
mainTemplate: {
parameters: ['payload'],
item: {
type: 'Sequencer',
description: 'Play this audio back in sequence',
items: [
{
type: 'Silence',
duration: 1500,
},
{
type: 'Speech',
contentType: 'PlainText',
content: _pFollowOn,
},
],
},
},
},
datasources: {
},
};
// iterate over the urls and add them to the list
_.forEach(_pUrls, function (url) {
let lArrayItem = { 'type': 'Audio', 'description': lDescription, 'source': url };
lRtn.document.mainTemplate.item.items.unshift(lArrayItem);
});
return lRtn;
}
Upvotes: 1
Views: 41
Reputation: 1074148
TypeScript infers the type of the lRtn.document.mainTemplate.item.items
array as an array of this union type (except I've put the properties in the same order in both of them; TypeScript doesn't care about property order):
{
type: string;
duration: number;
contentType?: undefined;
content?: undefined;
} | {
type: string;
duration?: undefined;
contentType: string;
content: string;
}
That means all members must match one of those two object shapes. But the object you're trying to put in the array doesn't match, it has this shape:
{
type: string;
description: string;
source: any;
}
That doesn't have duration
(which it would need to match the first type of the union) and also doesn't have contentType
or content
(which it would need for the second type of the union). So you can't put it in that array.
You need to either give an explicit type the items
array that makes those properties options, or make your lArrayItem
object fit the shape of one of those union types, so it fits into the array.
The best way to explicitly give a type to that items
array would be to define a type for lRtn
:
interface ItemType {
type: string;
duration?: number;
contentType?: string;
content?: string;
}
interface ReturnType {
document: {
version: string;
type: string;
description: string;
mainTemplate: {
parameters: string[];
item: {
type: string;
description: string;
items: ItemType[];
};
};
},
dataSources: {
// ...
}
};
(probably in smaller parts than that) and use const lRtn: ReturnType = ...
to assign a type to the whole thing.
But you can also do it with an as
expression on the array:
interface ItemType {
type: string;
duration?: number;
contentType?: string;
content?: string;
}
// ...
const lRtn = {
// ...
items: [
{
type: 'Silence',
duration: 1500,
},
{
type: 'Speech',
contentType: 'PlainText',
content: _pFollowOn,
},
] as ItemType[], // <<============
// ...
};
Upvotes: 1