I am using an Angular (not AngularJS) application that I run via the terminal using the ng serve
command.
Everything builds and I can navigate to the Angular app locally through my browser, however when looking at the terminal I have noticed there are some build errors displayed in red displayed below.
✔ Compiled successfully.
⠋ Generating browser application bundles...
Error: src/app/components/posting/posting.component.ts:343:78 - error TS2339: Property 'then' does not exist on type 'false | Promise<unknown>'.
Property 'then' does not exist on type 'false'.
343 this.getVideoMediaData(file).then(a => this.validateFileAgainstConfig('instagram'));
~~~~
✔ Browser application bundle generation complete.
My getVideoMediaData()
looks like this
public getVideoMediaData(file) {
if (typeof file === 'undefined') {
return false;
}
return new Promise((resolve, reject) => {
this.postingService.getMetadata(file.url).subscribe(
data => {
resolve(data);
const errors = data.errors;
file.errors = [];
if (errors && errors.length > 0 ) {
errors.forEach(function(ffmpegError) {
file.errors.push({
'message': ffmpegError,
'validation': 'ffmpeg'
});
}, this);
}
},
errorResponse => {
reject(errorResponse);
}
);
});
}
What is causing this & how would be the best approach to fix this issue so I no longer receive this error in the terminal once it has finished building after running ng serve.
Expected outcome After running ng serve the app builds without any errors
Actual outcome After running ng serve the app builds and displays the "Property 'then' does not exist on type 'false'" error in the terminal.
CodePudding user response:
Your first if doesn't return a Promise
. Wrap false
with Promise.resolve(false)
or make the method async
and you should be fine.
Side-note:
You should check for truthyness
of file as it also considers null
besides from undefined
:
async getVideoMediaData(file): Promise<boolean> {
if (!file) return false;
return new Promise((resolve, reject) => {
this.postingService.getMetadata(file.url).subscribe(
data => {
resolve(data);
const errors = data.errors;
file.errors = [];
if (errors && errors.length > 0 ) {
errors.forEach(function(ffmpegError) {
file.errors.push({
'message': ffmpegError,
'validation': 'ffmpeg'
});
}, this);
}
},
errorResponse => {
reject(errorResponse);
}
);
});
}
Side-note-2:
You should also consider toPromise()
(RxJS 6 and lower) or firstValueFrom
(RxJS 7^) to transform that service observable into a Promise
async getVideoMediaData(file): Promise<boolean> {
if (!file) return false;
// if using RxJS 6 or lower
const data = await this.postingService.getMetadata(file.url).toPromise()
// RxJS 7
const data = await firstValueFrom(
this.postingService.getMetadata(file.url)
)
const errors = data.errors;
file.errors = [];
if (errors && errors.length > 0 ) {
errors.forEach(function(ffmpegError) {
file.errors.push({
'message': ffmpegError,
'validation': 'ffmpeg'
});
}, this);
}
return data
}
Side-note-3:
I suggest you restrain yourself from passing anonymous functions and use fat-arrows
when dealing with JS arrays as you don't have to deal with the this
mess that JS has. Also using map
is better than for-each
ing and pushing:
file.errors = Array.from(data.errors ?? []).map(ffmpegError => ({message: ffmpegError, validation: 'ffmpeg'}))