所有成员具有相同类型的类的类型

时间:2018-07-03 09:03:07

标签: typescript

这是我的课程:

class CONSTANT {
    static readonly PATH = new class {
        /** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
         *
         * @type {{AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: module:fs.PathLike; AFTER_EFFECTS_TEMPLATE_XML_VERSION: module:fs.PathLike; RELATIVE_PATH_TO_AFTER_EFFECTS: module:fs.PathLike; OUTPUT_DIRECTORY_NAME: module:fs.PathLike; INPUT_DIRECTORY_NAME: module:fs.PathLike; ASSETS_DIRECTORY_NAME: module:fs.PathLike}}
         */
        private readonly RELATIVE = new class {
            readonly AFTER_EFFECTS_TEMPLATE_FILENAME: fs.PathLike = '\\video-template.aep';
            readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = `\\assets\\aep-template\\src${this.AFTER_EFFECTS_TEMPLATE_FILENAME}`;
            readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
            readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
            readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
            readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
            readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
        }; 
    } 
}

我想输入RELATIVE匿名类,使其仅具有fs.PathLike类型的属性。是否可以不提及每个属性的类型?

PS:之所以这样而不是对象文字,是因为我可以将类的属性相互组合,请参见:https://stackoverflow.com/a/50929798/1311745

1 个答案:

答案 0 :(得分:0)

除了初始化表达式之外,没有其他方法可以让Typescript推断成员的类型。

我们可以达到类似的效果,

  1. 结果对象只能包含与fs.PathLike兼容的类型的字段(如果我们分配与fs.PathLike不兼容的类型,则会出现错误)
  2. 是否将所有字段的类型设为fs.PathLike,而不考虑为其分配的原始类型(可以是string | Buffer | URL);

为此,我们将使用一个额外的函数,该函数将接收其字段为隐式类型的对象。如果我们传入的对象的字段与fs.PathLike或其他路径的容器不兼容,则对函数通用参数的类型约束将触发错误。此函数将返回一个新类型,该类型将用fs.PathLike

替换所有原始字段类型
type PathLikeContainer<T> = {
    [P in keyof T] : T[P] extends fs.PathLike ? fs.PathLike : T[P] extends object ? PathLikeContainer<T[P]> : never;
}
function asPathContainer<T extends PathLikeContainer<T>>(p: T) : PathLikeContainer<T>{
    return p;
}

class CONSTANT {
    static readonly PATH = asPathContainer(new class {
        readonly RELATIVE = new class {
            readonly AFTER_EFFECTS_TEMPLATE_FILENAME = '\\video-template.aep';
            readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION = `\\assets\\aep-template\\src${this.AFTER_EFFECTS_TEMPLATE_FILENAME}`;
            readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION = '\\assets\\aep-template\\intermediates\\video-template.aepx';
            readonly RELATIVE_PATH_TO_AFTER_EFFECTS = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
            readonly OUTPUT_DIRECTORY_NAME = '\\output';
            readonly INPUT_DIRECTORY_NAME = '\\input';
            readonly ASSETS_DIRECTORY_NAME = '\\assets';
            //readonly INVALID = 0; // will be an error
        }; 
    })
}


CONSTANT.PATH.RELATIVE.AFTER_EFFECTS_TEMPLATE_BINARY_VERSION //fs.PathLike