Determine the output of a function based on specific parameters, which will be included as a component of the returned object

I am currently encountering an issue that I am unsure if it can be resolved.

function getOptions(
  period: { first: string; last: string },
  prefix?: string
){
  if (prefix) {
    return {
      [`${prefix}_first`]: formatDay(period.first),
      [`${prefix}_last`]: formatDay(period.last),
      [`${prefix}_month`]: format(new Date(), 'MMMM', {
        locale: i18n.t('datefns:format', { returnObjects: true }),
      }),
    }
  }

  return {
    first: formatDay(period.first),
    last: formatDay(period.last),
    month: format(new Date(), 'MMMM', {
      locale: i18n.t('datefns:format', { returnObjects: true }),
    }),
  }
}

I would like to ensure TypeScript returns the correctly typed object based on the prefix parameter. How can this be achieved?

The expected outcome is:

getOptions({first: '01', last: '10'}) // {first: string, last: string, month: string}
getOptions({first: '01', last: '10'}, 'christmas') // {christmas_first: string, christmas_last: string, christmas_month: string}

Answer №1

Revise your function to accept dual generic parameters for both the period (T) and the prefix (P). This enables you to deduce their specific types. Subsequently, you can remap the keys of the period to begin with the prefix unless it is undefined. (indicating no prefix argument was given to the function). I appended a new return type property month using a basic intersection type. It may be beneficial to create type aliases for these constants.

declare function getOptions<
  T extends { first: string; last: string },
  P extends string | undefined = undefined,
>(
  period: T,
  prefix?: P,
): {
  [K in keyof (T & { month: string }) as `${P extends undefined
    ? ""
    : `${P}_`}${K extends string ? K : never}`]: (T & { month: string })[K];
};

const options1 = getOptions({ first: "01", last: "10" });
// const options1: {
//     first: string;
//     last: string;
//     month: string;
// }

const options2 = getOptions({ first: "01", last: "10" }, "christmas");
// const options2: {
//     christmas_first: string;
//     christmas_last: string;
//     christmas_month: string;
// }

TypeScript Playground

Answer №2

To enhance the functionality, you can introduce an interface in the following manner:

interface CustomObjectStructure {
  [key: string]: any;
}

Following this, your method can be implemented as shown below:

  fetchSettings(
    duration: { initial: string; final: string },
    prefix: string = ''
  ) {
    const output: CustomObjectStructure={};
    prefix = prefix.length ? prefix + '_' : prefix;
    output[prefix + 'initial'] = processStartDate(duration.initial),
    output[prefix + 'final'] = processEndDate(duration.final),
    output[prefix + 'month'] = format(new Date(), 'MMMM', {
      locale: lang.translate('datefns:format', { returnObjects: true }),
    })
    return output;
  }

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

Encountered a Timeout error with Typescript and Jest: Async callback did not execute within the 5000 ms timeout set by jest.setTimeout.Timeout

I am currently learning how to create tests using Jest with Nodejs and typescript. However, when attempting to run a simple test to check the response status, I encountered the following error: Timeout - Async callback was not invoked within the 5000 ms ...

Issues with TypeScript Optional Parameters functionality

I am struggling with a situation involving the SampleData class and its default property prop2. class SampleData { prop1: string; prop2: {} = {}; } export default SampleData; Every time I attempt to create a new instance of SampleData without sp ...

The dynamic duo: Formik meets Material-UI

Trying to implement Formik with Material-UI text field in the following code: import TextField from '@material-ui/core/TextField'; import { Field, FieldProps, Form, Formik, FormikErrors, FormikProps } from 'formik'; import ...

Bring in Lambda layers on your local device

I've been trying to create a lambda function with a layer, but I'm stuck on how to get it running locally. Here's the current directory structure: - projectDir/ | - lambdas/ | | - match-puller/ | | | - scr/... | | | - index.ts | | ...

Is the detection change triggered when default TS/JS Data types methods are called within an HTML template?

I'm currently updating an application where developers originally included function calls directly in the HTML templating, like this: <span>{{'getX()'}}</span> This resulted in the getX method being called after each change dete ...

Encountering a 404 error when importing http/server in deno

The file named index.ts is located below import { serve } from "https://deno.land/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b0c3c4d4f0809e8186869e80">[email protected]</a>/http/server.ts"; function ...

Angular Leaflet area selection feature

Having an issue with the leaflet-area-select plugin in my Angular9 project. Whenever I try to call this.map.selectArea, VSCode gives me an error saying that property 'selectArea' does not exist on type 'Map'. How can I resolve this? I& ...

Angular version 6 and its routing functionality

Hey there, I need some help with setting up routers in my Angular app. Here is the code from my files: import {NgModule} from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const APP_ROUTES: Routes = [ {pa ...

Encountering difficulty in reaching the /login endpoint with TypeScript in Express framework

I'm currently working on a demo project using TypeScript and Express, but I've hit a roadblock that I can't seem to figure out. For this project, I've been following a tutorial series from this blog. However, after completing two parts ...

Utilizing Mongoose Typescript 2 Schema with fields referencing one another in different schemas

I'm currently facing an issue as I attempt to define 2 schemas in mongoose and typescript, where each schema has a field that references the other schema. Here's an example: const Schema1: Schema = new Schema({ fieldA: Number, fieldB: Sch ...

What steps should I take to create a React component in Typescript that mimics the functionality of a traditional "if" statement?

I created a basic <If /> function component with React: import React, { ReactElement } from "react"; interface Props { condition: boolean; comment?: any; } export function If(props: React.PropsWithChildren<Props>): ReactElement | nul ...

What is the best way to create a versatile svelte component that can be utilized across various projects?

Currently, I am in the process of developing two distinct web applications using svelte/typescript: Site A, which serves as the public-facing front end and must be optimized for speed and efficiency Site B, the administration UI where editors manage and u ...

Invoke the API when the value of a property in the SPFX property pane is modified

Here's a question that might sound silly, but I'll ask anyway. I have a dropdown field in my Property pane that is filled with all the lists from the current site. It's working fine. When I change the dropdown selection, it populates a pro ...

Retrieve the values of private variables within a defined function

While experimenting with typescript, I have encountered an issue that I can't seem to resolve. My project involves using Angular, so I will present my problem within that context. Here is a snippet of my code: class PersonCtrl{ private $scope: I ...

Is it possible to have a synchronous function imported in typescript?

// addons.ts export interface addon { name: string; desc: string; run: (someparam: any) => void; } export function loadaddons(): Array<addon> { let addons: Array<addon> = []; fs.readdirSync(path.join(__dirname, "addons")) .fi ...

Utilizing MUI for layering components vertically: A step-by-step guide

I am looking for a way to style a div differently on Desktop and Mobile devices: ------------------------------------------------------------------ | (icon) | (content) |(button here)| ----------------------------------------- ...

Error encountered: 'applePaySession.completeMerchantValidation' is not a valid object reference when attempting to process a successful apple pay payment

So, I'm having an issue with the user's payment going through but encountering undefined value when checking compatibility. I've been trying to debug this problem in my code snippet below: setCanDisplayApplePay() { var client = n ...

best way to transfer boolean variable from one angular service to another

Can anyone help me with passing a boolean value from one service to another service file in Angular? I'm encountering an issue where the boolean value is showing as undefined. I haven't been able to find any examples or documents related to this. ...

Astro component experiencing script tag malfunction within content collection

I'm trying to create something using a script tag, but for some reason the script doesn't seem to be working properly. Below is my content collection: --- title: Essay Similarity stakeholder: THESIS articleDate: 05 Feb 2023 projectStart: 2022-08 ...

Compiled TypeScript files are missing require statements for imported components

Recently delved into Angular 2 and encountered an unusual issue. I kicked off using the Angular 2 Quickstart repository on GitHub and incorporated some components with templates. For example: import { Component } from '@angular/core'; import { ...