Issue
I am trying to retrieve data from an specific leave in an object with a combination of 2 keys. I am having trouble correctly typing the key(s) for accessing the nested objects.
Given this object structure
const movies = {
"Shawshank Redemption": {
rating: 9,
versions: {
"Directors Cut": {
length: 111,
},
Cinema: {
length: 113,
},
},
},
"The Dark Knight": {
release: 2008,
versions: {
Standard: {
rating: 9,
length: 113,
},
},
},
};
type MovieKey = keyof typeof movies;
How can I correctly type the VersionKey in this method? Is it even possible?
function getMovieVersion(movie: MovieKey, version: VersionKey)
Solution
You want getMovieVersion()
to be a generic function in which movie
's type is a generic type parameter K
which is constrained to MovieKey
.
Then you can index into typeof movies
with K
as the key type, and then into the result with "versions"
as the key type, and then finally use keyof
the result to get version
. That is, if movie
is of type K
, then version
is of type keyof (typeof movies)[K]["versions"]
:
declare function getMovieVersion<K extends MovieKey>(
movie: K,
version: keyof (typeof movies)[K]["versions"]
): void;
You can verify that this works as expected:
getMovieVersion("Shawshank Redemption", "Cinema"); // okay
getMovieVersion("The Dark Knight", "Standard"); // okay
getMovieVersion("Shawshank Redemption", "Standard"); // error!
// -----------------------------------> ~~~~~~~~~~
// Argument of type '"Standard"' is not assignable
// to parameter of type '"Cinema" | "Directors Cut"'
If you also need to know specifically the literal type of version
so that you can get the specific type of the output, you can use two generic type parameters as follows:
declare function getMovieVersion<
MK extends MovieKey,
VK extends keyof (typeof movies)[MK]["versions"]
>(
movie: MK,
version: VK
): (typeof movies)[MK]["versions"][VK];
getMovieVersion("Shawshank Redemption", "Cinema").rating; // error
getMovieVersion("The Dark Knight", "Standard").rating; // okay
Answered By - jcalz
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.