#Help with typing a generic function with generic parameter

12 messages · Page 1 of 1 (latest)

upper osprey
#

Can someone help me out with this error? I'm having difficulty grokking the issue. I'm not sure what is the issue but I also wouldn't say that I'm an expert in Generics.

What I am looking to do is build a decorator function that will allow specialized behaviors to either be overridden or interjected into another function (when it allows but that isn't important). The withHooks function is a curried function (factory) that takes in another function that will/should specify it's own types and specifically it's return types.

This is the API

// TYPES
type DefReturns = string | number
type Route = <T = DefReturns>() => Promise<T>

interface TestRoute {
  foo: string
}

// FUNCTION SIGNATURE
const withHooks = <T>(fn: Route) => async (): Promise<void> => { /* */ })

Here is the function that I'm using with the HoF above (withHooks(/* */)). The highlighted part is the error below.

const testRoute = withHooks(async (): Promise<TestRoute> => { /* */ })
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The TypeScript error

Argument of type '(/* */) => Promise<TestRoute>' is not assignable to parameter of type 'Route'.
  Type 'Promise<TestRoute>' is not assignable to type 'Promise<T>'.
    Type 'TestRoute' is not assignable to type 'T'.
      'T' could be instantiated with an arbitrary type which could be unrelated to 'TestRoute'.ts(2345)

Thing is that I don't even think I typed out withHooks correctly. It's not that function that I think needs to be typed but rather it's fn: Route parameter but the following also gives an error so I'm not really sure how to fix this

export const withHooks = <T>(fn: Route<T>) => ...
                                 ^^^^^^^^
                                 // Type 'Route' is not generic.
#

Okay, I see one of the issues now. When I pulled everything out I got this error which I looked up. Still looking into the other issues.
error TS2315: Type 'Route' is not generic
From there I realized I needed to make a type change.

// My first iteration was incorrect
export type Route = <T = number>() => Promise<T>;

// This is the correct way (generic before the = sign)
export type Route<T = number> = () => Promise<T>;
rigid pumice
#

this works:

tall echoBOT
#
// TYPES
type DefReturns = string | number
type Route<T> = () => Promise<T>;

interface TestRoute {
  foo: string
}

// FUNCTION SIGNATURE
const withHooks = <T>(fn: Route<T>) => async (): Promise<void> => { /* */ }

const testRoute = withHooks(async (): Promise<TestRoute> => Promise.reject('not implemented'))
rigid pumice
#

which i think is where you were at too after your realization about the generic type rather than generic function

#

what are the other issues you are looking into?

tall echoBOT
#

@bold lintel Here's a shortened URL of your playground link! You can remove the full link from your message.

Kαʂιƙ<3#0470

Preview:```ts
// TYPES
type DefReturns = string | number

interface TestRoute {
foo: string
}

// FUNCTION SIGNATURE
function withHooks<
T extends (args: TestRoute) => unknown

(fn: T) {
// do smth
}

const testRoute = withHooks(
async (): Promise<TestRoute> =>
Promise.reject("not implemented")
)```

upper osprey
# bold lintel <@204314889081061376> maybe you expect this https://www.typescriptlang.org/play...

~~I ended up going with the version that @mkantor mentioned (and the one I figured out just a second earlier) but I did have a question about your version.

How is this read, or rather, how does this one work?~~

nvm, it's hard to read for me since the type is directly in the generic versus aliased like I normally do. This is a bit easier for me to read is all

type HookThingy = (args: TestRoute) => unknown

function withHooks <T extends HookThingy> (fn: T) { /* do smth */ }
terse yoke
#

are you asking about how generics work or something

upper osprey
#

I'm not the best at it but I do understand them just takes more practice than I have to get better is all. For that previous example my issue was reading it and I just need to get used to seeing them more is all. It's like anon function shorthand or currying. Just takes a bit to get used to seeing different formats.

#

!resolved