1

I'm trying to conditionally return either KML or GeoJSON (string and object types respectively), and I'm wondering how to assign a function like that through an interface on an Object method.

Say the object is

const api = {
  getGeometry(url, format) {
    return fetch(`${url}?format=${format}`)
  }
}

With an interface like this:

interface GeometryRequest {
  (url: string, format: 'kml'): Promise<string>
  (url: string, format: 'geojson'): Promise<GeoJSON.FeatureCollection<any>>
}

So I can get that to work as a plain function:

const geometryRequest: GeometryRequest = (url, format) => {
  return fetch(`${url}?format=${format}`)
}

I'm just wondering how I can assign a type to an object method in a similar way.

Here are a couple of methods I tried:

getGeometry<GeometryRequest>

getGeometry: GeometryRequest

Neither are proper syntax.

I've also added a simpler version of the same problem on TypeScript Playground. In the playground output's type is: const output: string | number. But it should be able to tell the type from the overloaded functions in the interface somehow.

Any help on this syntax problem would be appreciated! :)

3
  • Are you sure the playground link is the correct one? Also it is not clear to me what you want to accomplish. Could you post a snipet with what specifically does not work? Commented Jul 16, 2018 at 19:46
  • Shoot, I grabbed the wrong URL and lost it @TitianCernicova-Dragomir Commented Jul 16, 2018 at 19:50
  • Fixed. @TitianCernicova-Dragomir Thanks :) Commented Jul 16, 2018 at 19:52

1 Answer 1

3

Function expressions can't specify multiple overloads. We can simulate the effect in one of several ways

Use a type assertion to specify the public signatures of the function

const a = {
    b: function(c) {
        if (typeof (c) === 'string') {
            return parseInt(c)
        }
        return String(c)
    } as {
        (a: string): number
        (a: number): string
    }
}

Use conditional types to decide the return type based on the input type, although this will cause issues with the implementation when returning a value (the comp will not let you assign a value because it can't determine it to be safe)

const a = {

    b<T extends string|number>(c : T ):T extends string ?number: string {
        if (typeof (c) === 'string') {
            return parseInt(c) as any
        }
        return String(c) as any
    }
}

Use a function declaration inside a self executing function and return the declared function

const a = {
    b: (function () {
        function b(a: string): number
        function b(a: number): string
        function b(c) {
            if (typeof (c) === 'string') {
                return parseInt(c)
            }
            return String(c)
        }
        return b;
    })()
}
Sign up to request clarification or add additional context in comments.

1 Comment

Your first option is extremely preferable. In my TS Playground link, I simply added as Test to the end of the function (also redefining it as b: function(c) {. Thanks!

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.