Typescript: verify that a collection of record pieces can be assembled into a complete record

Can someone help me create a function that ensures all elements in a list correspond to one and only one piece of a record?

For example, I have the following type and want to extract pieces from it:

<RecordType>(list: Partial<RecordType>[]) => RecordType

How can I achieve this type checking for my specific scenario?

Here's an example with the 'Person' type:

type Person = {
  id: string;
  name: string;
  lastname: string;
};

fromPieces<Person>([
 { name: "oscar" },
 { id: "arst" },
 { lastname: "mendez" }
]) => ({
  name: "oscar",
  id: "arst",
  lastname: "mendez"
});

Answer №1

In my perspective, it seems unfeasible to statically typecheck every "Partial" of the "Type" in order to ensure that a complete "Type" can be constructed within a function.

However, a generic function could be implemented to combine these parts into a more comprehensive Partial object.

If you are considering this approach, here's a straightforward example:

const builder = <T> (...parts: Partial<T>[]):Partial<T> =>
  parts.reduce((acc, part) => ({...acc, ...part}), {})
  
builder<{x: number, y: number}>({x: 5}, {y: 3}) // This code snippet works fine

builder<{x: number, y: number}>({x: 5}, {z: 3}) // However, this one triggers an error

Answer №2

When working with recursive types, there is a dependency on order. By casting Person to Unions and converting it with EntriesOf, the conversion of Person to:

{ id: string } | { name: string } | { lastname: string }
must be done.

Subsequently, you can cast the union to an array with specific requirements for each type using UnionToTuple. This results in the conversion to

[{ id: string }, { name: string }, { lastname: string }]
.

This process ensures that every property is present on the input, but it does rely on order (however, this can be resolved).

type EntriesOf<Type> = { [Key in keyof Type]: Pick<Type, Key> }[keyof Type];

type UnionToTuple<T> = (
    (
        (
            T extends any ? (t: T) => T : never
        ) extends infer U ? 
            (U extends any ? (u: U) => any : never
        ) extends (v: infer V) => any ? V : never
        : never
    ) extends (_: any) => infer W ?
        [...UnionToTuple<Exclude<T, W>>, W]
        : []
);

type Person = {
  id: string;
  name: string;
  lastname: string;
};

function fromPieces<T>(arg: UnionToTuple<EntriesOf<T>>): T {
    return {} as T;
}

// Example of successful use
const test = fromPieces<Person>([
  { id: "" },
  { name: "" },
  { lastname: "test" }
])

// Example that will not work
const test1 = fromPieces<Person>([
  { name: "" },
  { id: "" },
  { lastname: "test" }
])

View live demo

Credits to https://github.com/microsoft/TypeScript/issues/13298#issuecomment-707364842 for the UnionToTuple type.

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

What is the proper way to create an alias for an enum in TypeScript?

In the process of refactoring a large codebase, I came across this original definition: export const enum Direction { NORTH, SOUTH, } and various instances of code using it, like so: console.log(Direction.NORTH); Now, with the updated definition ...

Creating a map based on data retrieved from a JSON response

I am currently faced with an issue involving data retrieved from an API in JSON format, where the entries are structured as maps with number keys. Due to this structure, I am unable to assign my result to the data structure below due to missing Map methods ...

Expanding the base class and incorporating a new interface

(Here is an example written using Typescript, but it applies to other cases as well) class IMyInterface { doC:(any) => any; } class Common { commonProperty:any; doA() { } doB() { } } class ClassA extends Common {} class Clas ...

Discovering ways to align specific attributes of objects or target specific components within arrays

I am trying to compare objects with specific properties or arrays with certain elements using the following code snippet: However, I encountered a compilation error. Can anyone help me troubleshoot this issue? type Pos = [number, number] type STAR = &quo ...

typescript Object that consists of properties from an array with a defined data type

I have an array consisting of strings. I am trying to transform this array into an object where each string is a property with specific attributes assigned to them. export interface SomeNumbers { name: string; value: number; } const arr = ['apple& ...

Angular 11 - Error: The 'fetch' method could not be executed on the 'Window' object due to an illegal invocation

I have encountered an issue with a dependency in my current project. This particular dependency relies on isomorphic-unfetch for its functionality. Strangely, I am able to run isomorphic-unfetch without any problems within Angular 11. However, when I inclu ...

Can Vue instances support private computed properties?

Vue is a versatile tool that I utilize for both service classes and components. When it comes to reactive computeds, they prove to be incredibly beneficial. However, I often find myself wanting a clear way to differentiate between public interface compute ...

The parameters 'event' and 'payload' do not match in type

Upon running the build command, I encountered a type error that states: Type error: Type '(event: React.FormEvent) => void' is not assignable to type 'FormSubmitHandler'. Types of parameters 'event' and 'payload&apos ...

What is the method for including as: :json in your code?

I have a file with the extension .ts, which is part of a Ruby on Rails application. The code in this file looks something like this: export const create = async (params: CreateRequest): Promise<XYZ> => { const response = await request<XYZ> ...

Exploring the concept of parent/child components in Angular 2 beta and how to efficiently validate form inputs from

My current project involves implementing a complex scenario in Angular2 (beta 0 with TypeScript in Plunker) that consists of two nested forms, each represented by a separate component. The primary component, called Word, serves as a representation of a wo ...

Similar to the getState() function in react-redux, ngrx provides a similar method in Angular 6 with ngrx 6

Recently, I developed an application with react and redux where I used the getState() method to retrieve the state of the store and extract a specific slice using destructuring. Here's an example: const { user } = getState(); Now, I am transitioning ...

Do Angular FormControl objects have the capability to accept input values of various types, or are they limited to TypeScript primitive types?

When creating a reactive form in Angular using FormControl objects in a FormGroup, I encountered an issue. While passing primitive arguments as values for an HTML input select control works fine, when passing an object of a self-defined class, the value in ...

Prevent updating components when modifying state variables

Introduction I've developed a React component that consists of two nested components. One is a chart (created with react-charts) and the other is a basic input field. Initially, I have set the input field to be hidden, but it becomes visible when the ...

Javascript/Typescript Performance Evaluation

I am looking to create a visual report in the form of a table that displays the count of each rating based on the date. The ratings are based on a scale of 1 to 5. Below is the object containing the data: [ { "Date": "01/11/2022", ...

When utilizing React and Expressjs to upload a file through REST, the request seems to stall indefinitely

Seeking assistance with a simple React page containing a form for file selection and submission. The file is uploaded to the server via a POST request using axios. Here's the code snippet for the client-side: import React, { useState } from "reac ...

TypeScript: "The type is generic and can only be accessed for reading." - Error code 2862

Consider this sample JS function that requires type annotations: const remap = (obj) => { const mapped = {}; Object.keys(obj).forEach((key) => { mapped[key] = !!key; }); return mapped; }; I am attempting to add types using generics (in ...

Encountering a problem with the chipGrid feature in Angular Material version

I am currently facing an issue with my angular material chip component. The versions I am using are Angular 16 and Material 16. Here are all my dependencies: "@angular/animations": "^16.0.4", "@angular/cdk": "^16.0.4&quo ...

Error message: NextJs throws aReferenceError when trying to access the document object on page refresh

encountered the error ReferenceError: document is not defined when attempting to refresh the page I am working on creating a component using react-quill and then calling that component within a page. This is my component : import React, { useState } from ...

The correct way to convert an object to JSON in Angular 2 using TypeScript

I am currently in the process of developing a simple CRUD application using Angular 2 that will allow me to manage products. The issue I am facing is with implementing the post method to create a new product. My backend is built on an ASP.NET Web API frame ...

Creating a form with required fields in Angular and using the ngIf directive

Update: modified the sample code to incorporate TypeScript for better clarity I have a form with various buttons for users to choose from. The submit button is initially disabled until a user selects a button. However, there's a unique requirement wh ...