Is there a way to set up a function so that it only accepts parameter types that are specifically mapped to certain other types?

For a project, I am currently developing a function that verifies whether a specific field is required by passing the field's name as an argument. My goal is to ensure that the function only accepts field names that are defined within the Config type and have a corresponding RequiredConfig with a 'required' property set. Initially, I was able to achieve this by setting the function parameter type as ValidationField as shown below:


type Field = 'name' | 'surname' | 'age' | 'height' | 'school';

type ValidationField = Extract<Field, 'name' | 'surname'>;
type RequiredConfig = {required?: boolean};
type ValidationConfig<T> = T extends ValidationField ? RequiredConfig : {};

type Config = {
    [K in Field]?: ValidationConfig<K> & {visible?: boolean};
}

const config: Config = {name: {required: true, visible: true}, surname: {required: true, visible: true}, age: {visible: false}}

const checkRequired = (field: ValidationField) => config[field]?.required

However, I am now curious if it is possible to achieve the same functionality without direct access to the ValidationField type, but only through the Config, ValidationConfig, and RequiredConfig types. Is there a way to accomplish this?


const checkRequired = <T extends Field>(field: Config[Field] extends ...? T : never) => config[field]?.required

Answer №1

If you are tasked with examining Config in order to recreate ValidationField, it appears that you should extract only those property names where the value can be assigned to RequiredConfig | undefined (the presence of undefined is due to the fact that optional properties always include undefined as a possible value when accessed):

type MyValidationField = { [K in keyof Config]-?:
    Config[K] extends RequiredConfig | undefined ? K : never
}[keyof Config]
//   ^? type MyValidationField = "name" | "surname"

This represents a distributive object type where we iterate through the keys of Config (utilizing the -? mapping modifier) to eliminate any anomalies related to optional properties), and verify if the property of Config is a RequiredConfig or not. If it is, the key name becomes the property, otherwise we assign never. We then access into the mapped type using keyof Config to obtain the union of relevant key names.

As seen, this results in

"name" | "surname"
, identical to ValidationField. Subsequently, your checkRequired() function will still function properly with MyValidationField instead of ValidationField:

const checkRequired = (field: MyValidationField) => config[field]?.required

Access Playground link for 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

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">< ...

How can one implement closure in Angular 4?

I am looking to implement a nested function within another function in Angular 4 for closure. However, when attempting the code below, I encounter an error stating "cannot find name innerFn" outerFn(){ let a = "hello"; innerFn(){ console.log(a ...

Typescript is issuing warnings when displaying errors for the RTK query

I am currently using React Ts and Rtk query. My goal is to display the API response error on the UI. While it's working, I am encountering a warning that prompts me to set an error type for the response errors. How can I incorporate an error type for ...

Property declarations require decorators to come before the name and all keywords

After creating a decorator called @Inject in my typescript file, the code looked like this: export class A{ @Inject() private b!: string @Inject() private c!: string } However, vscode flagged an error for me: export class A{ @Inject() ...

A bespoke Typescript implementation of nested lists containing numbers

Currently, I am trying to figure out how to declare and populate a TypeScript list of lists. The structure of the list should be as follows: List<CustomList<>, number> Typically, I would create a standard list like this: someList: { text: a ...

Encountered an issue in React Native/Typescript where the module 'react-native' does not export the member 'Pressable'.ts(2305)

I have been struggling to get rid of this persistent error message and I'm not sure where it originates from. Pressable is functioning correctly, but for some reason, there is something in my code that doesn't recognize that. How can I identify t ...

Exploring Angular 2: Unlocking the Power of Directives within Components

To display a dialog component on the main component page after clicking a button, I used directives in the following way: Within the template: <button id="goToTasksCases" class="btn btn-success btn-lg" (click)="doShowStartNewCase($event)">START A N ...

Angular 6 is experiencing an issue with the functionality of the file toggle JS

Currently, I am utilizing the file toggle.js within the Urban theme. In the HTML chatbox, using the img, the file toggle.js is hardcoded and is functioning properly. However, when implementing code in Angular 6, the toggle.js is not functioning as expecte ...

The parameter type 'router' cannot be replaced with the type 'typeof ...'. The 'param' property is not included in the type 'typeof'

I'm currently working on a node application using TypeScript and have set up routing in a separate file named 'route.ts' import home = require('../controller/homeController'); import express = require('express'); let ro ...

Using Firebase: retrieving getAdditionalUserInfo in onCreate of a Firebase Cloud function

Can anyone help me figure out how to retrieve extra data from a SAML login provider in the backend (firebase functions)? I can see the data on the client side but I'm struggling to access it in the backend. I've specified these dependencies for ...

verify this condition prior to executing the for loop in javascript

When working with a queue in Typescript (ES6) set to run on an interval of 1 ms, it's important to consider the most efficient approach for performance. 1. setInterval(() => { //if (this._queue.filter(a => !a.running && a.cbs.length) ...

Module TypeScript could not be located

Currently, I am in the process of converting my nodejs project from JavaScript to TypeScript. I have updated the file extensions from .js to .ts, but now I am encountering errors with require(). In an attempt to fix this issue, I have added the following c ...

Issue with AngularJS: The view is not being updated after a nested http call

There is a specific scenario where I am required to make a call to the Github API in order to fetch the information of a particular user. Following that, I need to issue another call to retrieve the repositories belonging to that user: search(login: strin ...

Transform each item in an array into its own separate array using JavaScript (ES6)

Transform each item in an array into a separate sub-array and then combine them into one array. inputArray = ['One', 'Two', 'Three'] Desired Result outputArray = [['One'],['Two'],['Three']] How ...

Changing an element within an item stored in Ionic Storage

Hello, I am currently attempting to update a specific part of an object stored in Ionic storage. The current data in the Storage looks like this: key : object value : {a: "1", b: "2", c: "3"} To modify one of the values to 10, I created the following fu ...

Exciting Dynamic Text Animation in React using styled components

I came across this cool jumping text effect on https://web.dev/patterns/animation/animated-words/ and wanted to incorporate it into my app. However, when I tried implementing the component in React, I encountered some issues. I created a styled component a ...

TypeScript Implementation of ES6 Arrow Functions

Just diving into Typescript, I'm struggling to figure out the solution. I tried researching and looked into destructuring, but still unable to make it work. import React from "react"; import { StyleSheet, Text, View } from "react-native"; const st ...

Refine the observable data

Trying to filter a list of items from my Firebase database based on location.liked === true has been a challenge for me. I've attempted using the traditional filter array method but have not had success. Can anyone suggest an alternative method to acc ...

Error encountered when importing a function in Typescript causes a compiler issue

When working with Typescript, I am utilizing the import function following the instructions provided at: https://github.com/Microsoft/TypeScript/issues/12933 My implementation looks like this: import("../myScriptToBeImported").then((module) => { ...

An error occurred while running React, Next.js, and Type Script: Unhandled Runtime Error - TypeError: Unable to access 'value' property of undefined

I have been working on a multi-page form and using the antd package to add some styling to it. On the main page of the form, I implemented the following code (making sure I imported everything required). export class CreateNewContract extends Component ...