Ionic7/Angular16中PDFmake文档构建报'svg'属性相关编译错误
问题场景
在Ionic 7.1 + Angular 16项目中使用PDFmake,按照官方示例编写文档定义代码,但编译时触发类型错误,提示缺少svg属性,而官方文档并未提及该属性。
原代码
createPdf(){ const formValue = this.myForm.value; // 获取表单内容 const image = this.photoPreview ? {image: this.photoPreview, width:300} : {}; // 有图片则展示,无则返回空对象 let logo = {}; if (formValue.showLogo){ logo = { image: this.logoData, width: 50}; } const docDefinition = { content: [ { columns: [ logo, { text: new Date().toTimeString(), alignment: 'right' } ] }, {text: "REMINDER", style: 'header'}, { columns: [ { width: '50%', text: 'From', style: 'subheader' }, { width: '50%', text: 'To', style: 'subheader' } ] }, { columns: [ { width: '50%', text: formValue.from }, { width: '50%', text: formValue.to } ] }, image , { text: formValue.text, margin: [0,20,0,20]}, ], styles: { header: { fontSize: 18, bold: true, margin: [0,15,0,0] }, subheader: { fontSize: 14, bold: true, margin : [0,15,0,0] } } } }
编译错误信息
Argument of type '{ content: ({ image: string; width: number; } | {
image?: undefined; width?: undefined; } | { columns: {}[]; text?:
undefined; style?: undefined; margin?: undefined; } | { text: string;
style: string; columns?: undefined; margin?: undefined; } | { ...; } |
{ ...; } | { ...; })[]; styles: { ...; }; }' is not assignable to
parameter of type 'TDocumentDefinitions'. Types of property
'content' are incompatible.
Type '({ image: string; width: number; } | { image?: undefined; width?: undefined; } | { columns: {}[]; text?: undefined; style?:
undefined; margin?: undefined; } | { text: string; style: string;
columns?: undefined; margin?: undefined; } | { ...; } | { ...; } | {
...; })[]' is not assignable to type 'Content'.
Type '({ image: string; width: number; } | { image?: undefined; width?: undefined; } | { columns: {}[]; text?: undefined; style?:
undefined; margin?: undefined; } | { text: string; style: string;
columns?: undefined; margin?: undefined; } | { ...; } | { ...; } | {
...; })[]' is not assignable to type 'Content[]'.
Type '{ image: string; width: number; } | { image?: undefined; width?: undefined; } | { columns: {}[]; text?: undefined; style?:
undefined; margin?: undefined; } | { text: string; style: string;
columns?: undefined; margin?: undefined; } | { ...; } | { ...; } | {
...; }' is not assignable to type 'Content'.
Type '{ image?: undefined; width?: undefined; }' is not assignable to type 'Content'.
Property 'svg' is missing in type '{ image?: undefined; width?: undefined; }' but required in type 'ContentSvg'.170 this.pdfObj = pdfMake.createPdf(docDefinition);
node_modules/@types/pdfmake/interfaces.d.ts:1052:5 1052 svg: string; ~~~ 'svg' is declared here.
尝试添加svg属性后的新错误
修改代码:
const image = this.photoPreview ? {image: this.photoPreview, width:300, svg: ''}: {};
触发新错误:
Type '{ image: string; width: number; svg: string; }' is not
assignable to type 'Content'.
Type '{ image: string; width: number; svg: string; }' is not assignable to type 'ContentSvg'.
Types of property 'image' are incompatible.
Type 'string' is not assignable to type 'undefined'.
解决方案
问题根源是TypeScript类型推断失误:当this.photoPreview不存在时返回的空对象{},被TypeScript错误匹配到ContentSvg类型(该类型要求必填svg属性),而PDFmake的Content类型并不接受空对象。
方法1:条件添加内容项(推荐)
不要在content数组中放入空对象,而是通过条件判断决定是否添加对应内容:
createPdf(){ const formValue = this.myForm.value; // 先构建基础内容数组 const contentItems = [ { columns: [ // 无logo时用空字符串占位(PDFmake会忽略空文本) formValue.showLogo ? { image: this.logoData, width: 50} : '', { text: new Date().toTimeString(), alignment: 'right' } ] }, {text: "REMINDER", style: 'header'}, { columns: [ {width: '50%', text: 'From', style: 'subheader'}, {width: '50%', text: 'To', style: 'subheader'} ] }, { columns: [ {width: '50%', text: formValue.from}, {width: '50%', text: formValue.to} ] }, { text: formValue.text, margin: [0,20,0,20]} ]; // 仅当有图片时,插入到内容数组的指定位置 if (this.photoPreview) { contentItems.splice(4, 0, {image: this.photoPreview, width:300}); } const docDefinition = { content: contentItems, styles: { header: { fontSize: 18, bold: true, margin: [0,15,0,0] }, subheader: { fontSize: 14, bold: true, margin : [0,15,0,0] } } }; this.pdfObj = pdfMake.createPdf(docDefinition); }
方法2:显式指定类型
给变量指定Content类型,避免TypeScript错误推断:
import { Content } from 'pdfmake/interfaces'; // ... const image: Content = this.photoPreview ? {image: this.photoPreview, width:300} : ''; let logo: Content = ''; if (formValue.showLogo){ logo = { image: this.logoData, width: 50}; }
用空字符串代替空对象,PDFmake会自动忽略空文本内容。
内容的提问来源于stack exchange,提问作者dancingbush

