Typescript, accurately represent the behavior of a class method

I have few interfaces and a class that accepts an optional options object:

interface asObject { a: number, b: number }

interface options { returnAs: string; }

interface IA {
    go(): string;
    go(o: options): string | asObject;
}

class A implements IA {
    public go(o?: options): string | asObject {
        if(o&& o.returnAs && typeof o.returnAs === 'string') {
            switch(o.returnAs) {
                case 'object':
                    return { a: 5, b: 7 };
                default:
                    return 'string';

            }
        }
    }
}

      

And the error I am getting is "the class does A

not implement the interface correctly IA

".

If I try to overload the method:

...
public go(): string;
// Notice the parameter is no longer optional, ? removed.
public go(o: options): string | asObject { /* implementation as above */ }
...

      

Now I get: "The overload signature is incompatible with the function implementation."

I know I can just remove the overloaded signature on the interface IA

and remove the overloaded method in the class A

:

// Interface IA, notice the parameter is now optional, ? added.
go(o?: options): string | asObject;
// Class A
public go(o?: options): string | asObject { /* implementation as above */ }

      

Let me explain:

The class A

has a method named go

, if go

no options object is provided it will return a string, but if the user provides an options object, the return value depends on returnAs

what the string or object means.

My question is:

I don't think the solution I provided accurately reflects the behavior of the method go

.

Is there a way to keep the exact behavior for using typescript and not get errors like I did in my first 2 attempts above?

When I say exact behavior, I mean:

I'm looking for a way where typescript can output AObject

like string

:

var AObject = new A().go();

      

And he will be able to conclude AObject

as either string

, or asObject

:

var AObject = new A().go({ returnAs: 'object|string' });

      

I'm not 100% sure about typescript, in which case I'd be happy for a suggestion.

+3


source to share


1 answer


The easiest way is to declare the result A.go

as any

:

public go(o?: options): any {

      

Or declare a functional interface:

interface asObject { a: number, b: number }

interface options { returnAs: string; }

interface IGoFunction {
    (): string;
    (o: options): string | asObject;
}

interface IA {
    go: IGoFunction;
}

class A implements IA {
    go = <IGoFunction>function (o?: options): string | asObject {
        if (o && o.returnAs && typeof o.returnAs === 'string') {
            switch (o.returnAs) {
                case 'object':
                    return { a: 5, b: 7 };
                default:
                    return 'string';
            }
        }
    }
}

      



In fact, you don't even need to declare named interfaces:

class A {
    go = <{
        (): string;
        (o: options): string | asObject;
    }>function (o?: options): string | asObject {
    ...

      

The downside is that the function is added to every instance A

, but you can explicitly add it to the prototype:

class A {
    go: {
        (): string;
        (o: options): string | asObject;
    };
}

A.prototype.go = function (o?: options): any {
...

      

+3


source







All Articles