1

I need to translate these Java constructor overloads to 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;
}

I've tried create these constructors taking a look over there, but I've not been able to figure out how to get it...

Any ideas?

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 Answers 2

2

It seems what you actually want is to support any combination of present or missing parameters, with simple defaults. With 3 parameters, there are 8 on/off combinations. So while TypeScript supports overloading, writing out 8 overloads for type safety is not ideal.

But using named parameters (instead of positional) will simplify the implementation. More parameters can be added easily without writing exponentially more overloads.

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

Sign up to request clarification or add additional context in comments.

Comments

2

In typescript you can specify multiple signatures for a method/constructor but a single implementation. It is up to the implementation to figure out which overload was called.

In your case it might look something like this:

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;
}

Note: The implementation signature is hidden from the outside world (i.e it is not considered for resolution when looking for the apropriate constructor). This is why we have the empty constructor signature twice, once for public consumption, and once as the implementation signature.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.