Is there a TypeScript type that represents a subset of the keys of another type?

When given an object, is it possible to create a second typed object that contains only a subset of the original keys with different value types? I attempted to use Partial<keyof ...>, but it did not have the desired effect. Is there another approach to typing the second object (mapping as shown in the example below)?

For example: (on TypeScript Playground)

const obj = {
    a: '1',
    b: '2',
    c: 3,
    d: 4,
    e: false,
    f: 'Hmmm',
};

// The following code snippet results in an error:
// Type '{ a: number; b: number; }' is missing the following properties from type 'Record<"a" | "b" | "c" | "d" | "e" | "f", number>': c, d, e, f(2739)
const mapping: Record<keyof typeof obj, number> = {
    a: 10,
    b: 20
};


// The same error occurs when using Partial<>
// Type '{ a: number; b: number; }' is missing the following properties from type 'Record<Partial<"a" | "b" | "c" | "d" | "e" | "f">, number>': c, d, e, f(2739)
const mapping2: Record<Partial<keyof typeof obj>, number> = {
    a: 10,
    b: 20
};

// A similar error occurs when using Partial<> slightly differently
// Type '{ a: number; b: number; }' is missing the following properties from type 'Record<Partial<"a" | "b" | "c" | "d" | "e" | "f">, number>': c, d, e, f(2739)
const mapping3: Record<keyof Partial<typeof obj>, number> = {
    a: 10,
    b: 20
};

Answer №1

To define the type without relying on Partial, you can directly specify the value type needed for each key in the mapping:

const mapping: { [K in keyof typeof obj]?: number }= {
    a: 10,
    b: 20
};

Access Playground here

Answer №2

Partial<> functionally makes all properties of a type optional. Perhaps what you are seeking is a tweak on Pick<>, which facilitates creating a new type containing a subset of another type's properties.

However, while the types of the picked properties remain intact, they might need to be mapped to new types.

You can define a custom type for this purpose:

type PickNumber<Type, Keys extends keyof Type> = {
    [K in Keys]: number;
};

const value: PickNumber<typeof obj, 'a' | 'b'> = {
  a: 1,   // valid
  b: '2', // incorrect type
  c: 3,   // invalid property
};

In essence, what you aim to obtain is a subset of keys from a given type. You can extract a subset from a union of types using Extract<>.

Pick<> essentially accomplishes this task for you, but an alternative approach would involve:

type PickAlt<Type, Keys> = {
  [K in Extract<keyof Type, Keys>]: Type[K];
};

This involves applying Extract<> inline:

const value: {[K in Extract<keyof typeof obj, 'a' | 'b'>]: number} = ...;

Alternatively, in terms of the Record<> type:

const value: Record<Extract<keyof typeof obj, 'a' | 'b'>, number> = ...;

Playground

Answer №3

You're almost there!

let objectExample = {
    numberOne: '1',
    numberTwo: '2',
    numberThree: 3,
    numberFour: 4,
    booleanValue: false,
    randomString: 'Hmm'
};
const mappingValues: Partial<Record<keyof typeof obj, number>> = {
    numberOne: 10,
    numberTwo: 20
};
// or
const anotherMapping: { [K in keyof typeof obj]?: number }= {
    numberOne: 10,
    numberTwo: 20
};

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

Utilize VueJS to upload and visualize a file input on your website

I am currently working with TypeScript and Haml in conjunction with vue.js. My goal is to enable users to upload and view a file seamlessly using the vue.js framework. I have successfully managed to upload an image, however, I am facing an issue where the ...

How can one define a function type in typescript that includes varying or extra parameters?

// define callbacks const checkValue = (key: string, value: unknown) => { if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key) return value } const checkRange = (key: string, value: unknown, ...

What is the best way to transfer an array of objects between two components in React?

I've exhausted all the solutions found online, but I'm still facing a persistent issue. Despite my efforts, whenever I try to log information in another component, it keeps showing as undefined. (Just to clarify, the data being dealt with is an ...

A guide on implementing react-pose alongside @reach/router in a React Typescript project

I'm facing a challenge in my React app as I attempt to convert a JS example using react-pose and @reach/router to TypeScript, but unfortunately, it's not functioning properly. Below are the relevant typings from react-pose: import { ComponentTy ...

Having trouble assigning an initial value to ngx-bootstrap typeahead

Hello there, I am currently using Angular version 16 with ngx-bootstrap version 11.0.2. I am facing an issue where I cannot set a default value for a control. When a user selects data from a suggestive search and it gets saved in the database, I want that ...

Saving any type of file in SQL Server with a field type of varbinary(max) can be achieved by utilizing Angular with ASP.NET Core to create a REST API

I am currently facing an issue while attempting to save a file, such as an image, in the Microsoft SQL Server Management Studio through asp .NET core for the Rest API. I have managed to create a base64 representation of the file, but I am unsure about the ...

What is the best way to include text or a label on my Angular map without using a marker?

I am currently using the agm-map module in my angular project. I want to place a label or text at the center of a polygon on the map without using markers. How can I achieve this functionality in Typescript? I attempted to use the MapLabel Utility for thi ...

The type '{ domain: any; domainDispatch: React.Dispatch<any>; }' cannot be assigned to a type 'string'

Within my codebase, I am encountering an issue with a small file structured as follows: import React, { createContext, useContext, useReducer } from 'react' const initState = '' const DomainContext = createContext(initState) export co ...

Substitute all properties of a specific type with a predetermined value in Typescript using recursive substitution

If we consider the given type structure: type Person = { name: string age: number experience: { length: number title: string } } Can we create a type like this: type FieldsOfPerson = { name: true age: true experience: { length: t ...

Displaying sorted objects from Angular serviceIn Angular 8, let's retrieve an object

In my Angular8 application, I am running a query that fetches a data object. My goal is to sort this data object based on the order value and then display each product item on the browser. For example, here is an example of how the output should look like ...

Exploring the Differences Between Native Script and Ionic: A Guide to Choosing the Right Framework for Your Hybrid Apps

When deciding between Ionic and Native Script for hybrid app development, which technology would you recommend? Or do you have another suggestion knowing that I am familiar with Angular 6? Also, I am looking for a Native Script tutorial, preferably in vide ...

Could you explain the significance of the ^ symbol preceding a software version number?

Considering updating a package in my application, specifically the "@types/react-router-dom" from version "4.3.1" to "5.0.0". However, I'm hesitant as it is a large project and I don't want to risk breaking anything. While reviewing the package. ...

Transforming every piece of TypeScript code into JavaScript on the server-side

I'm relatively new to developing Node.js applications for production. I've created an app using TypeScript for the backend of my Node.js project. Currently, in the package.json file, I have the following script section: "scripts": { ...

Error in Angular 4: Unexpected 'undefined' provided instead of a stream

I encountered an issue while attempting to make a HTTP Post request. The error message I received is as follows: auth.service.ts?c694:156 Something went wrong requesting a new password, error message: You provided 'undefined' where a stream ...

Tips for implementing a personalized Circuit Breaker in Node.js that monitors request volume

Currently, I am exploring the most effective way to implement a circuit breaker based on the number of requests served in a Typescript/express application rather than fail percentage. Given that the application is expected to accommodate a large volume of ...

Generate a Jest dummy for testing an IncomingMessage object

I am facing a challenge in writing a unit test for a function that requires an IncomingMessage as one of its parameters. I understand that it is a stream, but I am struggling to create a basic test dummy because the stream causes my tests to timeout. : T ...

Error: The Turborepo package restricts the use of import statements outside of modules

I created a typescript "test" package in turborepo, which imports and exports typescript functions. Due to being in turborepo, it gets copied to node_modules/test. When attempting to run import {func} from "test", an error is thrown: SyntaxError: Cannot ...

Transform a collection of interfaces consisting of key-value pairs into a unified mapped type

I have a set of interfaces that describe key-value pairs: interface Foo { key: "fooKeyType", value: "fooValueType", } interface Bar { key: "barKeyType", value: "barValueType", } interface Baz { key: "bazKeyType", value: "bazValue ...

What are some strategies for circumventing the need for two switches?

My LayerEditor class consists of two private methods: export class LayerEditor { public layerManager: LayerManager; constructor() { this.layerManager = new LayerManager(this); } private executeCommand() { ...

Access the CSV file using Office365 Excel via a scripting tool

Objective I want to open a CSV file using Office365's Excel without actually saving the file on the client's machine. Challenge The issue with saving raw data on the client's machine is that it leads to clutter with old Excel files accumu ...