【问题标题】:Extending a method with typescript使用打字稿扩展方法
【发布时间】:2019-06-27 11:23:29
【问题描述】:

我创建了一个FileHandler 类,其中包含读取一个文件或多个类似文件的方法。

export class FileHandler {
    private static async readFileFromFileQuery (fq: FileQuery): Promise<File> {
        const { path, encoding, flag } = FileQueryHandler.make(fq);
        const content = await promisify(fs.readFile)(path, { encoding, flag })
        return { path, encoding, flag, content };
    }
    static async readFile (a: Path | FileQuery, b?: Omit<FileQuery, 'path'>): Promise<File> {
        if (typeof a === 'string') a = FileQueryHandler.getFromPath(a, b);
        return FileHandler.readFileFromFileQuery(a);
    }
    static async readFiles (a: (Path | FileQuery)[] | Directory, b?: Omit<FileQuery, 'path'>): Promise<File[]> {        
        if (a instanceof Array) return Promise.all(a.map(p => this.readFile(p, b)));
        return FileHandler.readFiles(PathHandler.getFromDirectory(a), b);
    }
    static async readFilesFromDirectory(a: Path | FileQuery, b?: Omit<FileQuery, 'path'>): Promise<File[]> {
        const ps = await DirectoryHandler.readDirectory(a);    
        if (typeof a === 'string') return await FileHandler.readFiles(ps, b);
        return await FileHandler.readFiles(ps, a);
    }
}

这是一个带有 static 方法的类,因为我不需要公开它们。

我现在想做的是扩展这个类。

我想将FileHandler.readFile 包装在try catch 中,并可能返回null,类似这样,其中方法名为readFile,但返回值与原始值不同。

export class FileOrNullHandler {
    async readFile (a: Path | FileQuery, b?: Omit<FileQuery, 'path'>): Promise<File | null> {
        return orNull(() => FileHandler.readFile(a, b));
    }
}

我还想免费获得所有其他方法,因为我看到的所有原始FileHandler 都是基于FileHandler.readFile

我尝试了一些将两者都转换为不使用 static 方法的方法,并且我还尝试了返回类型,但没有什么是简单的方法。

我需要的是:

  • 在两个类中的方法之间具有奇偶性
  • 让所有返回值代表类功能

我正在寻找最好的方法。

理想情况下,首先想到的是我将能够使用

  • static 调用 this 的方法
  • ReturnType&lt;this.method&gt;

但这两种东西都不存在。

我想要的是以下结果:

  • FileHandler.readFile 返回 File | null
  • FileHandler.readFiles 返回 File[]
  • FileHandler.readFilesFromDirectory 返回 File[]
  • FileOrNullHandler.readFile 返回 (File | null)
  • FileOrNullHandler.readFiles 返回 (File | null)[]
  • FileOrNullHandler.readFilesFromDirectory 返回 (File | null)[]

【问题讨论】:

  • 您根本不应该使用class。类旨在创建实例,而不是用作静态“方法”的集合。您正在寻找 TypeScript 命名空间或 JavaScript 对象字面量。
  • @Bergi 当然,您能否展示一下如何使用另一种语法扩展方法集?
  • 使用this 来引用方法看起来不错,然后您可以扩展您的FileHandler 对象,使用Object.create 的继承或@987654349 的副本@,然后覆盖readFile 函数。我不知道如何在 TypeScript 中正确输入,所以我不会发布答案。
  • 有趣,我有几个注意事项:为什么你需要扩展一些方法只是为了改变它的返回类型?如果你提到你只需要返回文件 | null,您可以使用打字稿来完成。此外,如果您需要扩展某些功能,则应将其添加到超类并扩展该类。所以你也可以重写基类方法。最后,在普通类中使用静态方法对我来说没有意义。我建议您添加应该是静态类或命名空间的实用程序。

标签: javascript typescript class oop ecmascript-6


【解决方案1】:

首先,拥有一个仅具有静态属性的类是没有意义的,那只是构建对象的一种非常复杂的方式:

export const FileHandler = {
   readFile (a: Path | FileQuery, b?: Omit<FileQuery, 'path'>): Promise<File> {
     // ...
   }
};

您可以将包装器创建为:

 const FileOrNullHandler = Object.assign(...Object.keys(FileHandler).map(key => ({
   [key]: function(...args) {
     return orNull(() => FileHandler[key](...args);
   }
 })));

【讨论】:

  • 导入到FileOrNullHandler 的方法如何知道现在使用“本地”ReadFile 方法?
【解决方案2】:

似乎静态类方法可以使用this,并进行扩展。但是类型仍然不准确。

export class FileHandler {
    static async readFileFromFileQuery (fq: FileQuery): Promise<File> {
        const { path, encoding, flag } = FileQueryHandler.make(fq);
        const content = await promisify(fs.readFile)(path, { encoding, flag })
        return { path, encoding, flag, content };
    }
    static async readFile (a: Path | FileQuery, b?: Omit<FileQuery, 'path'>): Promise<File> {
        if (typeof a === 'string') a = FileQueryHandler.getFromPath(a, b);
        return this.readFileFromFileQuery(a);
    }
    static async readFiles (a: (Path | FileQuery)[] | Directory, b?: Omit<FileQuery, 'path'>): Promise<File[]> {        
        if (a instanceof Array) return Promise.all(a.map(p => this.readFile(p, b)));
        return this.readFiles(PathHandler.getFromDirectory(a), b);
    }
    static async readFilesFromDirectory(a: Path | FileQuery, b?: Omit<FileQuery, 'path'>): Promise<File[]> {
        const ps = await DirectoryHandler.readDirectory(a);    
        if (typeof a === 'string') return await this.readFiles(ps, b);
        return await this.readFiles(ps, a);
    }
}

export class FileOrNullHandler extends FileHandler {
    static async readFileFromFileQuery (fq: FileQuery): Promise<File | null> {
        return orNull(() => FileHandler.readFileFromFileQuery(fq));
    }
}

【讨论】:

    【解决方案3】:

    我发现这种方法可以实现维护静态类的功能,但是FileOrNullHandler 中没有正确表示这些类型。

    export function sibling (v) {
        const staticClassName = v.toString().split ('(' || /s+/)[0].split (' ' || /s+/)[1];
        const m = {
            FileHandler,
            FileOrNullHandler
        }
        return m[staticClassName];
    }
    
    export class FileHandler {
        static async readFileFromFileQuery (fq: FileQuery): Promise<File> {
            const { path, encoding, flag } = FileQueryHandler.make(fq);
            const content = await promisify(fs.readFile)(path, { encoding, flag })
            return { path, encoding, flag, content };
        }
        static async readFile (a: Path | FileQuery, b?: Omit<FileQuery, 'path'>): Promise<File> {
            if (typeof a === 'string') a = FileQueryHandler.getFromPath(a, b);
            return sibling(this).readFileFromFileQuery(a);
        }
        static async readFiles (a: (Path | FileQuery)[] | Directory, b?: Omit<FileQuery, 'path'>): Promise<File[]> {        
            if (a instanceof Array) return Promise.all(a.map(p => sibling(this).readFile(p, b)));
            return sibling(this).readFiles(PathHandler.getFromDirectory(a), b);
        }
        static async readFilesFromDirectory(a: Path | FileQuery, b?: Omit<FileQuery, 'path'>): Promise<File[]> {
            const ps = await DirectoryHandler.readDirectory(a);    
            if (typeof a === 'string') return await sibling(this).readFiles(ps, b);
            return await sibling(this).readFiles(ps, a);
        }
    }
    
    export class FileOrNullHandler {
        static async readFileFromFileQuery (fq: FileQuery): Promise<File | null> {
            return orNull(() => FileHandler.readFileFromFileQuery(fq));
        }
        static readFile = FileHandler.readFile;
        static readFiles = FileHandler.readFiles;
        static readFilesFromDirectory = FileHandler.readFilesFromDirectory;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-07-07
      • 1970-01-01
      • 1970-01-01
      • 2017-04-02
      • 1970-01-01
      • 2019-09-18
      • 1970-01-01
      • 2018-05-30
      • 2020-05-13
      相关资源
      最近更新 更多