Расширение метода с помощью машинописи - PullRequest
0 голосов
/ 03 февраля 2019

Я создал 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 в попытку 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 методы, и я также экспериментировал с типами возвращаемых данных, но ничто не бросается в глаза как простой способсделайте это.

Мне нужно следующее:

  • Имеют паритет между методами в обоих классах
  • Все возвращаемые значения представляют функциональность класса

Я ищу лучший способ тo делать это.

В идеале первое, что приходит на ум, было бы то, что я мог бы использовать

  • static методов, которые вызывают this
  • ReturnType<this.method>

Но обе эти вещи не существуют.

Я хочу получить следующий результат:

  • FileHandler.readFile, который возвращаетFile | null
  • FileHandler.readFiles, который возвращает File[]
  • FileHandler.readFilesFromDirectory, который возвращает File[]
  • FileOrNullHandler.readFile, который возвращает (File | null)
  • FileOrNullHandler.readFiles, который возвращает (File | null)[]
  • FileOrNullHandler.readFilesFromDirectory, который возвращает (File | null)[]

Ответы [ 3 ]

0 голосов
/ 03 февраля 2019

Я нашел способ достижения этой функциональности, который поддерживает статические классы, но типы не представлены должным образом в 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;
}
0 голосов
/ 03 февраля 2019

Кажется, что методы статического класса могут использовать 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));
    }
}
0 голосов
/ 03 февраля 2019

Прежде всего не имеет смысла иметь класс только со статическими свойствами, это просто очень сложный способ создания объекта:

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);
   }
 })));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...