Reputation: 709
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 :)
Upvotes: 0
Views: 72
Reputation: 30999
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
}
// ...
}
Upvotes: 1