If you desire getMovieVersion()
to function as a generic method where the type of movie
is a generic type parameter K
that is restricted to MovieKey
.
By doing this, you can access typeof movies
using K
as the key type, then access the result with "versions"
as the key type, and finally utilize keyof
on the result to retrieve version
. Therefore, if movie
is of type K
, then version
will be of type
keyof (typeof movies)[K]["versions"]
:
declare function getMovieVersion<K extends MovieKey>(
movie: K,
version: keyof (typeof movies)[K]["versions"]
): void;
You can confirm that this functions as intended:
getMovieVersion("Shawshank Redemption", "Cinema"); // valid
getMovieVersion("The Dark Knight", "Standard"); // valid
getMovieVersion("Shawshank Redemption", "Standard"); // error!
// -----------------------------------> ~~~~~~~~~~
// Argument of type '"Standard"' is not assignable
// to parameter of type '"Cinema" | "Directors Cut"'
If you also require knowing the exact literal type of version
in order to acquire the specific type of the output, then you can use two generic type parameters as shown below:
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; // valid
Link to Playground for code execution