Create a custom data type that consists of a specific set of keys from an object

Is there a way to create a type in TypeScript that includes only a subset of keys from an object? Consider the example object below:

const something = {
  cannary: "yellow",
  coyote: "brown",
  fox: "red",
  roses: "white",
  tulipan: "purple",
  palmera: "green"
}

If I define a type like this:

type Something = keyof typeof something

Autocomplete and type checking will work for all keys, but what if I want to restrict it to only certain keys like:

type Animal = keyof typeof {only cannary|coyote|fox} 

Is this possible to achieve in TypeScript?

Answer №1

The Extract<T, U> type built into the system is a great option for this situation. It will...

Pull out the types from T that can be assigned to U

However, in your specific scenario, this still permits

Extract<keyof typeof something, 'cannary' | 'coyote' | 'monkey'>

to go through, even though 'monkey' is not present in T.

A slight adjustment to the Extract<T, U> type from:

type Extract<T, U> = T extends U ? T : never;

to

type ExtractExact<T, U extends T> = T extends U ? T : never;

requires the user to specify a type for U that must be an extension of T.

Now:

type CausesTypeError = ExtractExact<keyof typeof something, 'cannary' | 'coyote' | 'monkey'>

would immediately point out any unintended issues in the IDE:

https://i.stack.imgur.com/kPy5o.png

Playground Link

Answer №2

According to @spender, the Extract function is designed to retrieve specific members from a set and can be utilized to fulfill your requirements.

An alternative option is to utilize the Pick method.

type AnimalsPicked = keyof Pick<typeof something, 'cannary' | 'coyote' | 'monkey'>
type AnimalsExtracted = Extract<keyof typeof something, 'cannary' | 'coyote' | 'monkey'>

The outcome remains the same.

If you require the object type in between:

type AnimalsObj = Pick<typeof something, 'cannary' | 'coyote' | 'monkey'>

Given that the broader issue you are attempting to address has not been provided, the following suggestions may or may not be relevant.

const something = {
  cannary: "yellow",
  coyote: "brown",
  fox: "red",
  roses: "white",
  tulipan: "purple",
  palmera: "green"
} as const;
const animals = (()=>{
   const {cannary,coyote,fox} = something;
   return {cannary,coyote,fox};
})();
// The UI displays:
// const animals: {
//   cannary: "yellow";
//   coyote: "brown";
//   fox: "red";
// }

Visit the playground for a demo.

Answer №3

You should consider utilizing the Pick<T> utility type

https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys

const items = {
  apple: 'red',
  banana: 'yellow',
  grape: 'purple',
  kiwi: 'green',
};

// type ItemsType = "apple" | "banana" | "grape" | "kiwi"
type ItemsType = keyof typeof items;

// type Fruits = "apple" | "banana" | "grape"
type Fruits = keyof Pick<typeof items, 'apple' | 'banana' | 'grape'>;

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

Angular offers pre-determined values that cannot be altered, known as "

I am currently learning Angular and TypeScript, and I came across a task where I need to create an object or something similar that allows me to define a readable but not editable attribute. In Java, I would have achieved this by doing the following: publ ...

The utility of commander.js demonstrated in a straightforward example: utilizing a single file argument

Many developers rely on the commander npm package for command-line parsing. I am considering using it as well due to its advanced functionality, such as commands, help, and option flags. For my initial program version, I only require commander to parse ar ...

Search through an array of objects and assign a new value

I am facing a challenge with an array of objects structured as shown below: [ { "e_id": "1", "total": 0 }, { "e_id": "3", "total": 0 } ] My objecti ...

Encountering a compilation error while trying to utilize a union type in a function parameter within an

As stated on https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html, it is recommended to utilize multiple types for a parameter in a function (refer to the union part) /* OK */ interface Moment { utcOffset(): number; ...

One can only iterate through the type 'HTMLCollection' by utilizing the '--downlevelIteration' flag or setting a '--target' of 'es2015' or above

I'm currently working on developing a loader for my static grid. I've incorporated the react-shimmer-skeleton package source code, but I'm encountering issues with eslint in strict mode. You can find the respective repository file by followi ...

What is the reason TypeScript does not display an error when assigning a primitive string to an object String?

From my understanding in TypeScript, string is considered as a primitive type while String is an object. Let's take a look at the code snippet below: let s: string = new String("foo"); // ERROR let S: String = "foo"; // OK It's interesting to ...

Show the values in the second dropdown menu according to the selection made in the first dropdown menu using Angular 8

My goal is to retrieve data and populate two dropdowns based on user selection. However, the code I've written isn't giving me the desired output and instead, errors are occurring. Being new to Angular, I would appreciate a review of my code. Her ...

Error: Unable to Locate Module (Typescript with baseUrl Configuration)

Struggling to implement custom paths in my TypeScript project, I keep encountering the "webpackMissingModule" error due to webpack not recognizing my modules. I've attempted various solutions without any success. Any suggestions or ideas? Some packa ...

What is the process for setting up a subrouter using React Router v6?

This is the current React Router setup I am using: const router = createBrowserRouter([ { path: "/", element: ( <Page activeNav="home" > <Home /> </Page> ) }, { ...

Enhanced Autocomplete Feature with Select All Option in MUI

Currently, I am utilizing Material UI (5) and the Autocomplete component with the option for multiselect enabled. In addition, I am implementing the "checkbox" customization as per the MUI documentation. To enhance this further, I am attempting to incorpor ...

What is the best way to conduct tests on Typescript modules that are not intended for

Even though the compiler accepts my current solution without any errors, the tests are still failing with the message "ReferenceError: myFunction is not defined". I am interested in testing the functionality of the following module using TypeScript: File1 ...

The predicament with arranging arrays

I'm working with an array that looks like this: [ { "TaskID": 303, "TaskName": "Test1", "TaskType": "Internal", "Status": "Processing", "IsApproved": false, "RowNumber": 1 }, { "TaskID": 304, ...

Unable to create resource in nestjs due to typeScript compatibility issue

Encountered an Error: TypeError: Cannot access 'properties' property of undefined Failed to execute command: node @nestjs/schematics:resource --name=post --no-dry-run --language="ts" --sourceRoot="src" --spec Attempts made ...

Trigger a class method in an event using Angular with Typescript

I am completely new to TypeScript and Angular, and I am attempting to create a basic drawing component on a canvas. However, I have reached a point where I feel lost and confused about my code. The concept of "this" in TypeScript has been a major stumbling ...

Custom Email Template for Inviting Msgraph Users

I'm currently exploring the possibility of creating an email template for the MS Graph API. I am inviting users to join my Azure platform, but the default email they receive is not very visually appealing. public async sendUserInvite(body: {email: < ...

Issues arise when attempting to include the src attribute within the template tag in a Vuejs and Laravel project

After starting a project with Vuejs and Laravel using Laravel Mix, I encountered an issue. When attempting to split my component into separate files and load them in the .vue file as follows: <template src="./comp.html"></template> &l ...

Is there a way to insert a secured page right before accessing the dashboard?

I am trying to create a locked page that will display a message when users access the web app from a mobile device and load a mobile layout page displaying a message like mobile is not supported. I was considering using document.addEventListener('DOMC ...

The setter of the computed property is failing to execute

Currently, I am working with a computed property that represents an object of a specific type defined within my Vuex Store. The goal is to utilize this property in my component using v-model. I have thoroughly set up getters and setters for this property a ...

Unable to load class; unsure of origin for class labeled as 'cached'

Working on an Angular 10 project in visual studio code, I've encountered a strange issue. In the /app/_model/ folder, I have classes 'a', 'b', and 'c'. When running the application in MS Edge, I noticed that only classes ...

The function's overloading is not compatible with its implementation

Currently, I am puzzled by the lack of functionality in some code that I am reviewing. The structure resembles this: function getValidity(x: "v1"): boolean; function getValidity(x: "v2"): { a: number; b: number }; function getValidity(x: any) { if (x == ...