Search code examples
angulartypescriptangular-signals

angular signal transform is not working with input.required


If i declare with input.required({transform: this.transformMe}) then i am getting

Type '(value: any) => any' is not assignable to type 'undefined'.(2322)

But If i declare with input({}, {transform: this.transformMe}) then it is working fine.

Also how to provide alias in input.required()

Playground-Link


Solution

  • Below is the type definition for input.required

    required: {
        /** Declares a required input of type `T`. */
        <T>(opts?: InputOptionsWithoutTransform<T>): InputSignal<T>;
        /**
         * Declares a required input of type `T` with a transform function.
         *
         * The input accepts values of type `TransformT` and the given
         * transform function will transform the value to type `T`.
         */
        <T, TransformT>(opts: InputOptionsWithTransform<T, TransformT>): InputSignalWithTransform<T, TransformT>;
    };
    

    If you notice, we are getting first type InputOptionsWithoutTransform being set because we have defined only a single type for <T> ({ id?: number; title?: string }) which is causing it to use the first one, instead of we set, both <T, TransformT>(<InputRequiredCustomType, InputRequiredCustomType>) it will take the second type and transform will become available!

    We can just add the property alias in the same place where we defined the transform and it works great!

    import { CommonModule } from '@angular/common';
    import { Component, booleanAttribute, input, output } from '@angular/core';
    
    export type InputRequiredCustomType = { id?: number; title?: string }; // <- changed here
    @Component({
      selector: 'app-each-post',
      standalone: true,
      template: `
          <h1>{{post()?.title}}</h1>
          <button (click)="onPost()">Action</button>
      `,
      imports: [CommonModule],
    })
    export class EachPostComponent {
      // where to add alias when using input.required
      post = input.required<InputRequiredCustomType, InputRequiredCustomType>({ // <- changed here
        alias: 'asdf',// <- changed here
        transform: this.transformMe,
      });
      // post = input({}, { transform: this.transformMe });
      onAction = output<{ id?: number; title?: string }>();
    
      transformMe(value: any) {
        return { ...value, title: 'my override title' };
      }
    
      onPost() {
        this.onAction.emit(this.post());
      }
    }
    

    Stackblitz Demo