Uncover the mystery behind the return value of a generic function in TypeScript

I can't seem to wrap my head around why TypeScript is behaving in the way described below.

Snippet

01| const dictionary: { [key: string]: unknown} = {}
02|
03| function set<T>(key: string, value: T): void {
04|    dictionary[key] = value;
05| }
06|
07| function get<T = unknown>(key: string): T {
08|    return dictionary[key] as T;
09| }
10|
11| set('foo', 'bar');
12|
13| const a: string = get('foo');
14|
15| const _b = get('foo');
16| const b: string = _b;

Playground Link

Behavior

TS throws an error on Line 16 but not Line 13.

Expectation

Considering that the generic type T of the get function defaults to unknown, I expected both Line 13 and Line 16 to trigger TS errors since unknown shouldn't be able to be assigned to a variable of type string. Surprisingly, it doesn't flag Line 13, and when I hover over the get function on Line 13, it shows the return value as a string instead of unknown.

I've spent hours trying to make sense of this behavior. Any assistance would be greatly appreciated.

Furthermore, as a follow up question, what modifications should I implement to prompt TypeScript to raise errors on both lines?

EDIT

Apologies for any confusion. I actually INTEND for TypeScript to throw errors on both Line 13 & Line 16, pushing me to specify the generic type string. In other words, I want it to require me to use get<string>('foo')

Answer №1

the unknown type cannot be assigned to any other type. If you explicitly declare that a string will be returned here:

const a: string = get('foo');

typescript will assume that the variable a should be of type string. However, in the next line, the output of your get function will be the default value for the generic T that you are providing.

const _b = get('foo');

and since the unknown type can only be itself and cannot be assigned to any other type, an error occurs.

But here is the solution to make it work:

 const _b = get<string>('foo');

by specifying the expected output as a string, the variable assignment in the following line will not throw an error:

const b: string = _b; // no error here

Answer №2

The type unknown can only be assigned to itself (potentially any, but I haven't verified this). But, if you use any as the default type, your issue will be resolved:

01| const data: { [key: string]: any } = {}
02|
03| function assign<T>(key: string, value: T): void {
04|    data[key] = value;
05| }
06|
07| function retrieve<T = any>(key: string): T {
08|    return data[key] as T;
09| }
10|
11| assign('foo', 'bar');
12|
13| const x: string = retrieve('foo');
14|
15| const _y = retrieve('foo');
16| const y: string = _y;

In my opinion, using any is more appropriate in such cases.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a function that takes a second parameter inferred from a mapped type, depending on the first parameter given

Here is a snippet of code similar to the example provided: export enum Group { FOO = 'foo', BAR = 'bar', BIZ = 'biz' } interface Mapping extends Record<Group, any> { [Group.FOO]: {fooString: string; fooN ...

What causes inability for JavaScript to access a property?

My current coding project involves the usage of typescript decorators in the following way: function logParameter(target: any, key : string, index : number) { var metadataKey = `__log_${key}_parameters`; console.log(target); console.log(metadataKey ...

What could be causing the elements in my array to appear as undefined?

https://i.stack.imgur.com/ze1tx.png I'm stuck trying to understand why I can't extract data from the array. const usedPlatformLog: Date[] = [] users.forEach(el => { usedPlatformLog.push(el.lastUsed) }) console.log(usedPlatformLog) // disp ...

Error: The selected module is not a valid top-level option

I am facing an issue while using the babel-loader. I have removed all irrelevant code and just kept the error-related portion. What could be causing this problem? module.exports = merge(baseWebpackConfig, { ... module: { rules: [ ...

Angular Http Promise is not returning the expected value

Struggling to update my component property with an HTTP result, but encountering issues. Thank you for your assistance! (currently using a static mock object) Class - Object export class Gallery { name: string; } Service import { Injectable } from ...

Is there a way to utilize "npm install ts-node-dev -D" in Termux?

npm ERR! code EACCES npm ERR! syscall symlink npm ERR! path ../acorn/bin/acorn npm ERR! dest /storage/emulated/0/bot-baiano/node_modules/.bin/acorn npm ERR! errno -13 npm ERR! Error: EACCES: permission denied, unable to create symlink fro ...

initiate an animated sequence upon the initialization of the Angular server

Is there a way to launch a Netflix animation after my server has started without success using setTimeout? I don't want to share the lengthy HTML and CSS code. You can view the code for the animation in question by visiting: https://codepen.io/claudi ...

What methods can I employ to trace anonymous functions within the Angular framework?

I'm curious about how to keep track of anonymous functions for performance purposes. Is there a way to determine which piece of code an anonymous function is associated with? Here's an example of my code: <button (click)="startTimeout()&q ...

Adjust the size of an Angular component or directive based on the variable being passed in

I'm looking to customize the size of my spinner when loading data. Is it possible to have predefined sizes for the spinner? For example: <spinner small> would create a 50px x 50px spinner <spinner large> would create a 300px x 300p ...

Is there a method to make changes to files on a deployed Angular application without the need to rebuild?

After deploying my Angular application on a production environment using the command npm run build --prod --base -href, I now need to make changes to some static HTML and TypeScript files. However, since the app is already bundled and deployed, I'm un ...

In Typescript, if at least one element in an array is not empty, the function should return false without utilizing iterators

My current approach involves receiving a string array and returning false if any of the elements in the array is false. myMethod(attrs: Array<String>) { for (const element of attrs) { if (!element) { return false; } } ...

Explore one of the elements within a tuple

Can we simplify mapping a tuple element in TypeScript? I'm seeking an elegant way to abstract the following task const arr: [string, string][] = [['a', 'b'], ['c', 'd'], ['e', 'f']] const f ...

Separating the time and date into distinct variables offers flexibility in how they

Struggling with formatting time in a web component using TypeScript and React. The code below is working: new Date(myDate) .toLocaleTimeString( 'en-US', { weekday: 'short', year: 'numeric', month: 'short', ...

Implementing Typescript with React: Assigning event.target.name to state

I am facing an issue with a React state that has specific named keys defined in an interface... Despite trying a potential solution based on the state keys, I am still encountering an error... { [x: string]: string; }' provides no match for the sign ...

Storing an image in MongoDB using Multer as a file from Angular is not working as anticipated

I'm currently dealing with an issue that I believe is not functioning correctly. I installed a library in Angular called cropper.js from https://github.com/matheusdavidson/angular-cropperjs. The frontend code provided by the developer utilizes this li ...

No default export found in Module: TypeScript RestAPI

The word controller is showing a red underline when I use import controller from '../controllers/test.controller'; In my typescript rest api application, the structure looks like this... project structure I am puzzled by the red line under cont ...

Encountering a type error with gatsby-plugin-dark-mode in a Typescript Gatsby setup

Issue with Layout warning in index.tsx when hovering: (alias) const Layout: ({ children }: Props) => JSX.Element import Layout Type '{ children: Element[]; }' is missing the following properties from type 'Props': theme, >toggle ...

There seems to be an issue with the authorization function in nextauthjs utilizing TypeScript

In my NextJS application utilizing nextAuth with TypeScript, I am encountering difficulties implementing the credentials provider. Below is a snippet from my api\auth\[...nextauth]\route.ts file: CredentialsProvider({ name: 'cre ...

React Redux Bundle with Hot Reload Feature

Working on a project written in TypeScript with the React and Redux framework, I'm familiar with webpack and its middleware libraries for hot reloading. My question arises when considering how my TypeScript code is first converted to JSX through gulp ...

The local types package cannot be built by react-scripts even though tsc has successfully completed the process

I have developed an application with a TypeScript frontend and backend. To streamline the process, I decided to create a shared types module that contains all the necessary types for both components in one centralized location. Rather than going through th ...