0

I'm really confused here. This is also an extension of this if you need any extra detail.

This is my code:

interface Collections extends Twitter.Collections, Coin.Collections {}
type CollectionName = keyof Collections
type CollectionType <T extends CollectionName> = Collections[T]

const _collections: {
    [K in CollectionName]?: Collection<CollectionType<K>>
} = {}

export async function getCollection<T extends CollectionName> (name: T): Promise<Collection<CollectionType<T>>> {
    if (name in _collections && typeof _collections[name] !== 'undefined') {
        return _collections[name]
    }

    ...
}

It's on this last if line that the following ts error displays:

Type '{ "twitter:tweets"?: Collection<Tweet> | undefined; "twitter:users"?: Collection<User> | undefined; "twitter:metadata-cashtag"?: Collection<CashtagMetadataDb> | undefined; "coins:all"?: Collection<...> | undefined; }[T]' is not assignable to type 'Collection<Collections[T]>'.
    Type 'Collection<Tweet> | Collection<User> | Collection<CashtagMetadataDb> | Collection<Coin> | undefined' is not assignable to type 'Collection<Collections[T]>'.
        Type 'undefined' is not assignable to type 'Collection<Collections[T]>'.

As you can see, I've tried my best to type check here but I'm unable to get this to work.

Thanks for your help :)

3
  • 1
    The code provided is not enough to reproduce the error. But I think it's related to [K in CollectionName]? being optional. It could be fixed using definite assertions return _collections[name]! (note the exclamation mark), but again I'm not sure since the code provided is not enough Commented Aug 31, 2018 at 9:41
  • And I don't know if you're returning the correct type after the if clause. So this could be another error Commented Aug 31, 2018 at 9:47
  • When I remove the ? in [K in CollectionName]? that error goes away but I can't fill the object on declaration. I'll have to use the bang, !, which I never knew about before. Thanks for your help :) Commented Aug 31, 2018 at 15:38

1 Answer 1

1

Automatic narrowing doesn't work on element access expressions like _collections[name]. If you want to take advantage of narrowing, you'll have to save the value in a local variable before testing it. And due to limitations on how TypeScript reasons about lookup types, you'll need a type annotation on that local variable. This should work:

export async function getCollection<T extends CollectionName>(name: T): Promise<Collection<CollectionType<T>>> {
    let coll: Collection<CollectionType<T>> | undefined = _collections[name];
    if (coll !== undefined) {
        return coll
    }
    // ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

Can you please collect the complete code to reproduce the error in the question so I can debug?

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.