Reputation: 1651
In the following minimal example I get the typescript error: TS2339: Property 'creationDate' does not exist on type 'B[keyof B]
. I hope you can help me to find a way to express this usecase in a better way, so that this error doesn't happen.
interface Entry<V> {
value: V;
creationDate: string
}
type Book = PaperBook | AudioBook;
interface PaperBook {
title: Entry<string>;
numPages: Entry<number>;
}
interface AudioBook {
title: Entry<string>;
duration: Entry<number>;
}
function getCreationDate<B extends Book>(book: B, key: keyof B) {
return book[key].creationDate; // <- Error happens here
}
See this typescript playground
In getCreationDate()
I am trying to access book[key].creationDate
which gives an error. It looks like I need to somehow tell typescript that no matter what key we use to access my book
object, I promise you will always find an Entry
object there.
Maybe the problem lies in <B extends Book>
? What i actually would want to express here is something like:
"B
is either PaperBook
or AudioBook
" or "B
is one of the types that underly the union type Book
"
Hope this makes sense and you have a solution for me, thank you!
Upvotes: 0
Views: 55
Reputation: 4934
It is not safe because B extends Book
can have other keys. Consider the following (following the definitions in the original post):
const naughtyBook = {
title: { value: "title", creationDate: "today" },
numPages: { value: 200, creationDate: "yesterday" },
badValue: "Not an entry",
}
getCreationDate(naughtyBook, "badValue");
This will clearly fail.
Upvotes: 0
Reputation: 42188
extends
means that B
could include additional properties which have any value, not necessarily an Entry
. One way to fix this is to require that all values on B
are an Entry
like so:
function getCreationDate<B extends Book & Record<string, Entry<any>>>(book: B, key: keyof B) {
return book[key].creationDate;
}
B
extends
the Record
, so we don't actually widen the key type.
Normally I would say that you don't want a generic at all here and that you should just require book
to be a Book
, but with different keys on the two branches of the union that is difficult.
Upvotes: 2