Typescript如何处理类型或类型数组

时间:2019-02-09 14:01:05

标签: typescript types

express-fileupload具有如下声明:

declare namespace fileUpload {
class FileArray {
    [index: string]: UploadedFile | UploadedFile[]
}

interface UploadedFile {
    name: string;
    encoding: string;
    mimetype: string;
    data: Buffer;
    truncated: boolean;
    mv(path: string, callback: (err: any) => void): void;
    mv(path: string): Promise<void>;
}

然后在控制器Iam中将其用作:

const file: UploadedFile | UploadedFile[] = req.files.file;

但是现在TypeScript的功能

Property 'name' does not exist on type 'UploadedFile | UploadedFile[]'. 
Property 'name' does not exist on type 'UploadedFile[]'.

用于文件名

在数组类型中,没有原因。

tyo如何处理这种情景?尝试

if (file instanceof Array)
if (file typeof UploadedFile[])

但这不起作用。

1 个答案:

答案 0 :(得分:2)

if (file typeof UploadedFile[])部分将不起作用,因为typeof是JS运行时检查,而UploadedFile[]是一种类型。类型的概念在运行时并不真正存在,因此无法执行该语句。

但是首先检查file是否为数组应该足够了。通过编写处理类型UploadedFile | UploadedFile[]的代码,您基本上信任分配给该类型的变量,使其在运行时具有该类型的值。因此,如果它不是数组,则必须为UploadedFile类型的值:

if (Array.isArray(req.files.file)) {
    // It must be an array of UploadedFile objects...
} else {
    // It must be a single UploadedFile object...
}

繁琐的部分是,只要变量具有这样的联合类型,就必须编写类似于if ...的结构,否则要在该变量上执行操作的任何地方(读取,转换,或以其他方式使用它)。有没有更清洁的方法?

您可以将file的值规范化为始终为数组,然后始终将其视为这样

如果req.files.file是一个数组,则将myFiles设为req.files.file。否则,使myFiles为包含1个元素的数组,该元素为req.files.file

const myFiles: UploadedFile[] = Array.isArray(req.files.file)
    ? req.files.file
    : [req.files.file];

现在考虑拥有一个功能handleSingleFile,您必须为来自req.files.file的所有文件运行该功能。不用写:

if (Array.isArray(req.files.file)) {
    req.files.file.forEach((file) => handleSingleFile(file));
} else {
    handleSingleFile(req.files.file);
}

...您知道myFiles将始终是一个数组:

myFiles.forEach((file) => handleSingleFile(file));