Inputting data into a static object without changing its keys' data type

Consider the following interface and object:

interface Person {
  name: string;
  lastName?: string;
}

const obj: { [key: string]: Person } = {
  a: { name: 'John' },
  b: { name: 'Jane', lastName: 'Doe' },
}

This structure allows keys of any string type for the object. However, there is a desire to retain key inference in a static fashion.

One possible solution involves specifying keys explicitly like so:

type ObjKeys = 'a' | 'b';

const obj: { [key in ObjKeys]: Person } //...

Nevertheless, this method can be considered overly wordy.

Is there a shorter way to declare "here's the type for all values of this object while preserving statically defined keys?"

Answer №1

To accomplish this task, you'll need more than just type-level actions. When you specify the type of obj as {[k: string]: Person}, the compiler assumes it is the definitive type and doesn't refine it further based on the assignment like {a: {...}, b: {...}}. The process of flow control analysis applies only to types that are a union, and {[k: string]: Person} isn't one.

In such scenarios, I often create a custom generic function like the identity function below, allowing the compiler to deduce the intended type:

const asPersonDict = <K extends PropertyKey>(
  o: { [P in K]: Person }) => o;

Now, utilize this helper function rather than directly specifying the type:

const obj = asPersonDict({
  a: { name: 'John' },
  b: { name: 'Jane', lastName: 'Doe' },
});

/* const obj: {
    a: Person;
    b: Person;
} */

Link to Playground with code

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

"Encountering an issue with opening a form in a child component from the parent - receiving an error message 'unable to access

Here's the scenario: I am working with a list of companies that each have an array of projects as one of their variables. The desired functionality is to display the list of companies in the parent component/html, and only open a child component to sh ...

Utilizing Angular 2 for Element Selection and Event Handling

function onLoaded() { var firstColumnBody = document.querySelector(".fix-column > .tbody"), restColumnsBody = document.querySelector(".rest-columns > .tbody"), restColumnsHead = document.querySelector(".rest-columns > .thead"); res ...

The type declaration for the Storage.prototype.setObject method

I'm facing a challenge in creating a d.ts file for the given DOM feature. Storage.prototype.setObject = function(key:string, value:any) { this.setItem(key, JSON.stringify(value)); } Storage.prototype.getObject = function(key:string) { var va ...

Ways to prevent scrolling in Angular 6 when no content is available

I am developing an angular 6 application where I have scrollable divs containing: HTML: <button class="lefty paddle" id="left-button"> PREVIOUS </button> <div class="container"> <div class="inner" style="background:red">< ...

Tips on Showing a Unique List in Mat-Table?

Here's what I'm trying to accomplish: I have a list and I want to display it without any duplicates. I attempted using the code (this.model.map(x => x.map), but it resulted in an error. Can anyone help me fix this? model: myModel[]; myObj:any; ...

Is it Beneficial to Combine jQuery with TypeScript in Angular 7?

Our school project team is venturing into the world of Angular and TypeScript, but we all admit to being newbies in this area. I've mainly focused on the design aspect of our project and left the coding to my teammates. However, I recently completed ...

Incorporating DefinitelyTyped files into an Angular 2 project: A step-by-step guide

I am currently developing an application using angular 2 and node.js. My current task involves installing typings for the project. In the past, when starting the server and activating the TypeScript compiler, I would encounter a log with various errors rel ...

Error: The module parsing process failed due to the presence of an octal literal in strict mode. To resolve this issue,

I'm currently attempting to incorporate the following regular expression into Angular6: const regexp = new RegExp('^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2])\\2))(? ...

Error encountered when an Angular expression is changed after it has already been checked in a dynamically generated component

I am encountering a problem with Angular and the CdkPortal/CdkPortalHost from @angular/cdk. I developed a service that allows me to associate a CdkPortalHost with a specified name and set its Component at any given time. This is how the service is struc ...

Creating dynamic key objects in TypeScript with index signatures: A beginner's guide

How can the code be optimized to automatically initialize a new product type without adding extra lines of code? Failure to initialize the variable results in a syntax error. enum ProductType { PC = 'pc', LAPTOP = 'laptop', TV ...

Using Typescript: How to access a variable beyond the scope of a loop

After creating an array, I need to access the elements outside of the loop. I am aware that they are not in the scope and using 'this.' before them does not grant access. colIdx = colIdx + this.columns.findIndex(c => c.editable); this.focusIn ...

Using TypeScript to validate the API response against specific types

I'm intrigued by the scenario where you expect a specific data type as a response from fetch / Axios / etc, but receive a different type instead. Is there a way to identify this discrepancy? interface HttpResponse<T> extends Response { parsed ...

Generic type array does not display property

I feel like I must be overlooking something. It seems too straightforward to be causing issues for me. Database.ts export class Database { id: number; } search-input.ts import { Database } from './../resources/database'; import { Inje ...

Calculate the total by subtracting values, then store and send the data in

Help needed with adding negative numbers in an array. When trying to add or subtract, no value is displayed. The problem seems to arise when using array methods. I am new to arrays, could someone please point out where my code is incorrect? Here is my demo ...

Display the following information as you iterate through an array in TypeScript within a React component

Currently, I am working on adding data to two separate arrays in a React TypeScript project. const [deviceNames, setDeviceNames] = useState<Array<string>>([]) const [serialNumbers, setSerialNumbers] = useState<Array<string>>([]) ...

Unlocking the Power of PropTypes.shape in TypeScript

Currently, I am in the process of migrating a React application from Javascript to Typescript. However, I am encountering difficulties, particularly with migrating the shape PropType. The code I have right now looks like this: import React from 'reac ...

Struggling to conceal the code with a Jasmine Spy

I have been creating test cases to ensure code coverage using TypeScript. Despite using Jasmine's spyOn, I have encountered an issue where some methods are not covered, although no errors are being reported. Your guidance on resolving this matter woul ...

Leveraging generics within TypeScript

I have developed a class in TypeScript that uses generics. export class ModelTransformer { static hostelTransformer: HostelTransformer; static fromAtoB(instance: T): U { if (instance instanceof HostelType) { return ModelTrans ...

Create object properties as optional, declare them afterwards, and access them without needing to verify

I'm wondering if there's a way to work around type definitions. Let me provide an example to clarify my question. Suppose I want to define a type that consists of a large object containing multiple objects: type BigObject = { dom: HTMLElement, ...

Trigger a change event for a Material Checkbox by referencing its unique identifier

<div *ngFor="let cus of deselectedList | keyvalue" (click)="clickCheckBox('customer_'+cus.key+'_checkbox')"> {{cus.key}} <mat-checkbox id="customer_{{cus.key}}_checkbox" (change ...