Obtaining the value from a TypeScript hashmap: Using a getter function or setting a

Looking to create a simple getter for retrieving a value from an object with string keys, or returning a default value of the same type when necessary. This situation arises frequently when working with Maps in Typescript. The main focus is on accessing top-level values without delving into nested data structures. Here is the current implementation:

function getValueOrDefault<T>(
  object: Record<string, T>,
  path: keyof Record<string, T> & string,
  orDefault: T
): T {
  if (path in object && object[path] !== undefined) {
    return object[path] as T;
  } else {
    return orDefault;
  }
}

The issue here is that TypeScript continues to infer that `T` could potentially be `undefined`, even after explicitly checking `if object[path] !== undefined`. This leads to the need for casting with `as T`, which is not optimal. Is there a better approach to achieving the desired behavior?

Answer №1

To achieve the desired outcome, you can follow this approach:

function fetchValueOrDefault<T extends object, K extends keyof T>(
  data: T,
  key: K,
  defaultValue: T[K]
): T[K] {
  if (data[key] !== undefined) {
    return data[key];
  }
  return defaultValue;
}

const x = fetchValueOrDefault({ x: 'apple', y: 7}, 'x', 'default');
   // ^? const x: string

const y = fetchValueOrDefault({ x: 'apple', y: 7}, 'y', 7);
   // ^? const y: number

const myObj: {z?: string} = {}
const z = fetchValueOrDefault(myObj, 'z', 'default');
   // ^? const z: string

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

reactjs: disable a specific eslint rule

I'm trying to figure out how to disable the "no-unused-vars" rule specifically for TypeScript interfaces. Here's a code snippet where I'm getting a warning: export type IKeoTableColumn<T> = { id: T; align: 'left' | ' ...

Error: The argument passed to the function must be an Array type. Undefined value was received instead of an array

Looking for some assistance with this coding issue, hoping someone with expertise can lend a hand! (Not my forte) I've written this Typescript code snippet for a basic CloudFunction export const add2list = functions.https.onRequest((req:any , res:any ...

How can I exclude *.d.ts files from tslint checking?

Recently, I decided to integrate tslint into my workflow. Following the installation steps, I used the command: npm install tslint tslint-config-ms-recommended --save-dev My configuration file tslint.json now looks like this: { "extends": "tslint-co ...

What is the best way to export an overloaded function in TypeScript?

Trying to figure out how to overload a function in TypeScript so it can determine the type of arg2 based on the value of arg1. Arg1 has a list of known values. Here's a rough example of what I'm attempting: interface CatArgs {legs : number} int ...

The value of type 'X' cannot be assigned to type 'Y' or 'undefined'

In my code, there is a component that requires a prop with an enum value: export enum AType { some = "SOME", word = "WORD", } const MyComponent = (arg: AType) => {} When I try calling this component like so: <MyComponent ar ...

When attempting to send an email with nodemailer, an error message popped up saying "setImmediate is not defined."

let transporter = nodemailer.createTransport({ host: "sandbox.smtp.mailtrap.io", port: 2525, auth: { user: "xxxxxx", pass: "xxxxxx" }, tls: { rejectUnauthorized: false } ...

TypeScript does not throw a compiler error for incorrect type usage

In my current setup using Ionic 3 (Angular 5), I have noticed that specifying the type of a variable or function doesn't seem to have any impact on the functionality. It behaves just like it would in plain JavaScript, with no errors being generated. I ...

A simple guide on how to send an Angular component to the Nebular dialog service

My current project involves creating a web dialog in Angular6 using Nebular components. Initially, I used the method of passing an <ng-template> reference in the following manner: openAddDialog = (dialogTemplate: TemplateRef<any>) => { ...

Can a TypeScript variable in Angular contain a mixture of HTML and plain text?

I have a website where I am displaying content from a Model file. I would like to create a TypeScript variable that contains both a string related to the website's content and a URL enclosed in an HTML tag. When this variable is rendered on the view, ...

Using `it` with accessing class members

When testing whether a specific object/class is correctly wired up, I often utilize it.each to prevent writing repetitive tests. The issue arises when the type of the object doesn't have an index signature, requiring me to cast it to any for it to fun ...

Having trouble navigating typescript's "import" syntax in conjunction with compiler options like module and choosing between esnext and commonjs?

I am facing an issue with my typescript project that includes mocha tests. Here is a snippet of how the tests start: import { assert } from "chai"; import "@material/mwc-ripple"; //I need to test a script that uses this describe("simple test", () => { ...

Utilize React Styled Components to seamlessly unify the styles of two different components

I want to have consistent styles for both a styled input element and a styled select element. Currently, I accomplish this using string interpolation: const styles = ` background-color: white; width: 100%; border: 0 solid transparent; bor ...

Is it possible to overlook specific attributes when constructing an object using TypeScript interfaces?

I have defined an interface with various properties. I am looking to instantiate an object based on this interface, but I only want to partially initialize some of the properties. Is there a way to accomplish this? Thank you. export interface Campaign { ...

Instructions for adding a select dropdown feature in Angular 6 that includes a search filter. Additionally, tips on how to filter objects by their name property

I need to add an auto-complete feature in my Angular 6 app where the data is displayed as objects in a dropdown and filtered as we type. **template.html** <mat-form-field > <input matInput [matAutocomplete]="auto" [formControl]="customerFi ...

Developing a TypeScript PureMVC project from scratch

Currently, I am working on a project to implement PureMVC in TypeScript using npm and grunt. Unfortunately, PureMVC has ended development on their project and there is a lack of resources for PureMVC in TypeScript online. The documentation only provides in ...

Changing Enum Value to Text

In my enum file, I have defined an object for PaymentTypes: export enum PaymentTypes { Invoice = 1, CreditCard = 2, PrePayment = 3, } When I fetch data as an array from the database, it also includes PaymentType represented as numbers: order: ...

Is it possible in Angular Typescript to map the attributes of an array to a class object or generate a new object using the elements of the array?

Here are the specifications of the tools I am currently using: Angular CLI: 10.0.6 Node: 12.18.2 Operating System: win32 x6 Angular Version: 10.0.10 My goal is to retrieve selected rows from ag-grid using a specific method. When I retrieve the row, i ...

Filtering a key-value pair from an array of objects using Typescript

I am working with an array of objects containing elements such as position, name, and weight. const elements = [{ position: 3, name: "Lithium", weight: 6.941, ... },{ position: 5, name: "Boron", weight: 10.811, ... }, { position: 6, name: "Carbon", weight: ...

Utilizing the map function in Angular while disregarding any null values

I have an array of objects in my dataset. Here's a glimpse of how it is structured: [ { "id": 1, "name": "john", "address": { "number": 42, "street": "High Street"} }, { ...

Display the submission timestamp in Angular upon clicking the submit button

How can I capture the date and time when a user clicks the submit button in Angular? For example, if a form with name and email inputs is filled out and submitted, I want to display the date and time along with the name and email in a table. Here is some ...