Angular 18 custom input: FormControl has strange behavior

I’m struggling with some strange behavior while using my custom input component.

First of all, I built a simple abstract class that has the main “features” and methods of the component, then, the input-component which has very few code:

// Abstract class

export abstract class BaseFormInput<T> implements ControlValueAccessor, Validator, AfterViewInit, OnDestroy {
    @Input() label: string
    @Output() onChange: EventEmitter<T> = new EventEmitter<T>()

    private changeInternal: (obj: T) => void
    private changeSub: Subscription
    private disabled$ = new BehaviorSubject(false)
    private required$ = new BehaviorSubject(false)

    public input = new FormControl(null)

    ngOnDestroy() {
        this.changeSub.unsubscribe()
    }

    ngAfterViewInit() {
        this.changeSub = this.input.valueChanges.subscribe(v => {
            if (!this.disabled$.getValue()) {
                this.onChange.emit(v)
                this.changeInternal(v)
            }
        })
    }

    writeValue = (obj: T) => this.input.setValue(obj)

    registerOnChange = (fn: (obj: T) => void) => this.changeInternal = fn

    registerOnTouched = (_fn: (obj: any) => void) => {}

    setDisabledState = (isDisabled: boolean) => this.disabled$.next(isDisabled)

    validate(control: AbstractControl): ValidationErrors {
        this.required$.next(control.hasValidator(Validators.required))

        // THIS LINE HAS WEIRD BEHAVIOR
        console.log(control, control.errors)

        return null
    }

    public get isDisabled$(){
        return this.disabled$.asObservable()
    }

    public get isRequired$(){
        return this.required$.asObservable()
    }
}

The input component is simply designed like this:

@Component({
    selector: "ec-input-text",
    template: `<div class="form-control">
            <label *ngIf="label">
                {{ label }}
                <span *ngIf="isRequired$ | async">*</span>
            </label>
            <input *ngIf="type !== 'textarea'" [type]="type" [formControl]="input" [attr.disabled]="isDisabled$ | async" />
            <textarea *ngIf="type === 'textarea'" [formControl]="input" [attr.disabled]="isDisabled$ | async"></textarea>
            <ng-template></ng-template>
        </div>`,
    changeDetection: ChangeDetectionStrategy.OnPush,
    providers: [
        { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputTextComponent), multi: true },
        { provide: NG_VALIDATORS, useExisting: forwardRef(() => InputTextComponent), multi: true }
    ]
})
export class InputTextComponent extends BaseFormInput<string> {
    @Input() type: "text" | "password" | "email" | "textarea" = "text"
    @Input() maxLength: number
}

Finally, I created a register-component, which uses the input.

HTML:

<form [formGroup]="form">
    <ec-input-text label="First name" formControlName="firstName" />
    <ec-input-text label="Last name" formControlName="lastName" />
    <ec-input-text label="E-mail" formControlName="email" type="email" />
    <ec-input-text label="Password" formControlName="password" type="password" />
</form>

The TS of the register-component has a public property like this:

public form = new FormGroup({
        firstName: new FormControl(null, [Validators.required, Validators.maxLength(50)]),
        lastName: new FormControl(null, [Validators.required, Validators.maxLength(50)]),
        email: new FormControl(null, [Validators.required, Validators.maxLength(100)]),
        password: new FormControl(null, Validators.required)
    })

Now, the issue is the following: in the validate method of the abstract class (where I put a comment), I tried to log the control errors, and I get a strange behavior: when logging the formControl, I can see in the console that the property errors is null, but if I log control.errors it logs:

{ required: true }

Even though the control is valid and I typed the value (in fact, control.value has a value and results valid).
So if i do:

console.log(control)

And I expand it, errors is null (expected behavior, correct!)

But if I do:

console.log(control.errors)

It is valorized (not correct, the control is valid!)

How can I figure this out? Thanks in advance!