Search code examples
typescript

Why must literals be hardcoded to work in TypeScript?


I am making a search engine for tv shows and movies and it's working but the only issue I have right now is that media_type has to be hardcoded to be either "tv" or "movie".

If I set it to "tv" then it will show me the details of the tv show but I can’t see movie details and if I set it to "movie" it only shows details of movies but not tv shows. I need it to work for both dynamically.

The URL will be formatted like either of these:

localhost:3000/tv/1434
localhost:3000/movie/65215
getMediaDetails: async ({
    mediaId,
    media_type
}: {
    mediaId: number | null;
    media_type?: "movie" | "tv";
}) => {
    if (!mediaId) {
        throw new Error("Media ID must be provided.");
    }
    const endpoint = `${media_type}/${mediaId}`;
    const response = await httpClient
        .get(endpoint, {
            searchParams: {
                append_to_response: "credits",
                language: "en-US"
            }
        })
        .json<MediaDetailsResponse>();
    response.name = response.title || response.name; // Unified 'name' attribute
    return response;
}

Solution

  • A literal is a more concrete sub-type of a collective type. What this means is that "Hello World" is a string, but a string is not "Hello World" in the type system.

    If you declare a variable using var or let for example:

    let mediaType = "movie";

    And pass this variable mediaType to getMediaDetails(), Typescript will infer that it is a string and hence this will not work. [1]

    But using const to declare a variable will inform TypeScript that this object will never change so TypeScript can correctly set the type to be "Hello World" and not string.


    But using const is as good as hardcoding isn’t it? A better solution is to declare an actual type for example:

    type MediaType = "movie" | "tv";

    Now in getMediaDetails(), use the actual type:

    /* •••Rest of code•••*/
    media_type?: MediaType;
    /* •••Rest of code•••*/

    And a correct variable declaration would be:

    let mediaType: MediaType = "movie";

    [1] Remember that "Hello World" is a string, but a string is not "Hello World" in the type system.