Creating a Typescript interface where one property is dependent on another property

Let's look at an illustration:

type Colors = {
  light: 'EC3333' | 'E91515'
  dark: '#100F0F' | '140F0F' 
}

interface Palette {
  colorType: keyof Colors
  color: Colors[keyof Colors]
}

Is it possible for the type of the color property to be dependent on the colorType property?

This means that when selecting colorType light, the type of color should be 'EC3333' | 'E91515'

Answer №1

Representing Palette as a single non-generic interface is not possible, but you can create a union of each desired combination of colorType and color:

type Palette = {
    colorType: "light";
    color: "EC3333" | "E91515";
} | {
    colorType: "dark";
    color: "#100F0F" | "140F0F";
}

To automatically generate this union type from Colors, you can map over the keys of Colors and then immediately index into the resulting mapped object type:

type Palette = { [K in keyof Colors]: {
  colorType: K
  color: Colors[K]
} }[keyof Colors]; 

By using IntelliSense, you can verify that this results in the same type as before, with the added benefit of automatic updates if Colors change.


With this union type, you can now use Palette and ensure that the constraints are enforced and understood:

const badPalette: Palette = {
  colorType: "dark",
  color: "E91515" 
} // error!

const goodPalette: Palette = {
  colorType: "dark",
  color: "140F0F" 
} // okay

Playground link to 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

Using Bazel, Angular, and SocketIO Version 3 seems to be triggering an error: Uncaught TypeError - XMLHttpRequest is not recognized

Looking to integrate socket.io-client (v3) into my Angular project using Bazel for building and running. Encountering an error in the browser console with the ts_devserver: ERROR Error: Uncaught (in promise): TypeError: XMLHttpRequest is not a constructor ...

Applying ngClass to a row in an Angular material table

Is there a way I can utilize the select-option in an Angular select element to alter the css-class of a specific row within an Angular Material table? I have successfully implemented my selection functionality, where I am able to mark a planet as "selecte ...

Managing multiple asynchronous requests through Observables in web development

I am working on an Angular2 website that sends multiple ajax requests using Json Web Tokens for authorization when it is initialized Here are two examples: public getUser(): Observable<User> { // Code block to get user data } public getFriends ...

Adding an element to an array does not automatically reflect on the user interface

After fetching JSON data from the endpoint, I am attempting to update an array but not seeing the expected results on the frontend. export class LocationSectionComponent implements OnInit{ myControl = new FormControl(); options : string[] = [' ...

Utilizing either Maps or Objects in Typescript

I'm in the process of developing a simple Pizza Ordering App. The concept is, you select a pizza from a list and it's added to a summary that groups all the selections together. Here's how I want it to appear: Pizza Margarita 2x Pizza Sala ...

TypeScript throws an error when jQuery is imported unexpectedly

How does the compiler resolve the $ in the code snippet below, even without importing jQuery? function f () { $('#loadFiles').click() // ok $$('#loadFiles').click() // error, can't find name '$$' } The compile ...

In Angular 5 HTTP GET request, the value "null" is being converted to ""null""

I'm currently in the process of transitioning our application from Angular 4 to Angular 5. In Angular 5, when passing an object model as parameters, if one of the values is null, it gets converted to a "null" string which is causing issues for us. Her ...

Clicking on the image in Angular does not result in the comments being displayed as expected

I find it incredibly frustrating that the code snippet below is not working as intended. This particular piece of code was directly copied and pasted from an online Angular course I am currently taking. The objective of this code is to display a card view ...

An issue has occurred where all parameters for the DataService in the D:/appangular/src/app/services/data.service.ts file cannot be resolved: (?, [object Object])

Upon running the command ng build --prod, an error is encountered. Error in data.service.ts: import { BadInput } from './../common/bad-input'; import { AppError } from './../common/app-error'; import { Injectable } from '@angular ...

Limiting the parameter type in Node.js and TypeScript functions

Currently working on a Node.js project utilizing TypeScript. I'm attempting to limit the argument type of a function to a specific base class. As a newcomer to both Node and TypeScript with a background in C#, I may not fully grasp some of the langua ...

Issue with the height not being updated in a parent React nested Accordion

Currently, I am in the process of developing the mobile version of my homepage. However, there seems to be a bug in my nested accordion labeled "Projects." The bug is causing an issue where the bottom projects section does not display at the correct height ...

Tips for utilizing a formatter with a Doughnut chart in Angular using Chart.js

When using Chart.js with AngularJS, I tried to display numbers or percentages in a doughnut chart using a formatter. However, it did not work as expected. Here is how I implemented it in my HTML: <canvas baseChart class="chart" [data]="do ...

Using asynchronous data in Angular 2 animations

Currently, I have developed a component that fetches a dataset of skills from my database. Each skill in the dataset contains a title and a percentage value. My objective is to set the initial width value of each div to 0% and then dynamically adjust it t ...

TypeScript does not verify keys within array objects

I am dealing with an issue where my TypeScript does not flag errors when I break an object in an array. The column object is being used for a Knex query. type Test = { id: string; startDate: string; percentDebitCard: number, } const column = { ...

Challenges arise when dealing with generics in TypeScript

I'm a beginner in TypeScript and I'm trying to write a method with a generic type argument similar to what you can do in .Net. Here's the code snippet I've been working on: class TestObject { Id: number; Truc: string; Machin: str ...

When attempting to utilize expo-av in a React-Native project on iOS, the recorded MP4 file encountered an issue when trying to submit it as form data for Open

I've been working tirelessly through the night, trying to record myself on my iPhone using expo-av to capture speech and then upload it to openai's transcriptions endpoint with the whisper-1 model. The recording is saved as an mp4 file, which I ...

The parameter 'data' is assumed to have an 'any' type in React hooks, according to ts(7006)

It's perplexing to me how the 7006 error underlines "data," while in the test environment on the main page of React Hooks (https://react-hook-form.com/get-started#Quickstart), everything works perfectly. I'm wondering if I need to include anothe ...

Perfroming unit testing on base class using Jasmine and Angular framework

I have a common base class that I include in every grid component. Currently, I have the specifications for the grid component, but I want to create separate specifications for the base class in its own spec file. The goal is to eliminate redundant code ...

The Material Table in Angular is having issues with sorting functionality

I tried implementing the basic example from the angular material website, which displays a table with accurate data but the sorting functionality is not working as expected. For reference, you can view the StackBlitz demo here: https://stackblitz.com/edit ...

Error: Unable to locate the type definition file for the '@babel' package

I am currently working on a new project and here is the content of my package.json file. { "name": "dapp-boilerplate", "version": "1.0.0", "main": "index.js", "license": "MI ...