代码之家  ›  专栏  ›  技术社区  ›  Jordi

Typescript:重载级联式构造函数

  •  1
  • Jordi  · 技术社区  · 7 年前

    我需要将这些Java构造函数重载转换为Typescript:

    public QueryMixin() {
        this(null, new DefaultQueryMetadata(), true);
    }
    
    public QueryMixin(QueryMetadata metadata) {
        this(null, metadata, true);
    }
    
    public QueryMixin(QueryMetadata metadata, boolean expandAnyPaths) {
        this(null, metadata, expandAnyPaths);
    }
    
    public QueryMixin(T self) {
        this(self, new DefaultQueryMetadata(), true);
    }
    
    public QueryMixin(T self, QueryMetadata metadata) {
        this(self, metadata, true);
    }
    
    public QueryMixin(T self, QueryMetadata metadata, boolean expandAnyPaths) {
        this.self = self;
        this.metadata = metadata;
        this.expandAnyPaths = expandAnyPaths;
    }
    

    我试着创建这些构造函数,看看那里,但我还没有弄清楚如何得到它。。。

    有什么想法吗?

    constructor();
    constructor(metadata: QueryMetadata);
    constructor(metadata: QueryMetadata, expandAnyPaths: boolean);
    constructor(self: T);
    constructor(self: T, metadata: QueryMetadata);
    constructor(???) {
        this.self = self;  <<< ???
        this.metadata = selfOrMetadata;  <<< ???
        this.expandAnyPaths = expandAnyPaths;
    }
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   Robert Penner    7 年前

    看起来您实际上想要的是支持现有或缺失参数的任何组合,并使用简单的默认值。有3个参数,有8个开/关组合。因此,虽然TypeScript支持重载,但为了类型安全写出8个重载并不理想。

    但使用命名参数(而不是位置参数)将简化实现。可以轻松添加更多参数,而无需编写指数级的重载。

    interface QueryMetadata { }
    class DefaultQueryMetadata implements QueryMetadata { }
    
    interface QueryMixinParams<T> {
        self: T;
        metadata: QueryMetadata;
        expandAnyPaths: boolean;
    }
    
    class QueryMixin<T> implements QueryMixinParams<T> {
        self: T;
        metadata: QueryMetadata;
        expandAnyPaths: boolean;
    
        constructor({
            self = null,
            metadata = new DefaultQueryMetadata(),
            expandAnyPaths = true,
            }: Partial<QueryMixinParams<T>> = {}) {
            this.self = self;
            this.metadata = metadata;
            this.expandAnyPaths = expandAnyPaths;
            console.log(this);
        }
    }
    
    // Any combination of parameters is supported
    new QueryMixin();
    new QueryMixin({});
    new QueryMixin({ self: {} });
    new QueryMixin({ self: {}, metadata: {} });
    new QueryMixin({ self: {}, metadata: {}, expandAnyPaths: false });
    new QueryMixin({ self: {}, expandAnyPaths: false });
    new QueryMixin({ metadata: {} });
    new QueryMixin({ metadata: {}, expandAnyPaths: false });
    new QueryMixin({ expandAnyPaths: false });
    

    Try it in TypeScript Playground

        2
  •  2
  •   Titian Cernicova-Dragomir    7 年前

    在typescript中,您可以为一个方法/构造函数指定多个签名,但只能指定一个实现。由实现来确定调用了哪个重载。

    在您的情况下,它可能看起来像这样:

    constructor();
    constructor(metadata: QueryMetadata);
    constructor(metadata: QueryMetadata, expandAnyPaths: boolean);
    constructor(self: T);
    constructor(self: T, metadata: QueryMetadata);
    constructor() {
        let self: T = null;
        let metadata : QueryMetadata = null;
        let expandAnyPaths = true;
        if(arguments.length > 0) {
            // Asuming QueryMetadata is a class
            if(arguments[0] instanceof QueryMetadata) { 
                expandAnyPaths = arguments[1] || true;
                metadata = arguments[0];
            }
            else {
                self = arguments[0]
                metadata = arguments[1];
            }
        }
    
        this.self = self;
        this.metadata = metadata || new DefaultQueryMetadata();;
        this.expandAnyPaths = expandAnyPaths;
    }
    

    注: 实现签名对外部世界隐藏(即,在寻找合适的构造函数时,不考虑对其进行解析)。这就是为什么我们有两次空构造函数签名,一次用于公共消费,一次作为实现签名。