0

I encountered an interesting problem, there is such a service


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class TestService {
  static generate(url: string, response: string): string[] {
    return [url + response];
  }

  static testField = TestService.generate('aaa', 'vvv');

}


and default spec file


import { TestBed } from '@angular/core/testing';

import { TestService } from './test.service';

fdescribe('TestService', () => {
  let service: TestService;

  beforeEach(() => {
    TestBed.configureTestingModule({});
    service = TestBed.inject(TestService);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });
});

My test fails with this error: Uncaught TypeError: Cannot read properties of undefined (reading 'generate') TypeError: Cannot read properties of undefined (reading 'generate')

but it works if I change my tsconfig:

  1. Delete "useDefineForClassFields": false,

  2. Change "target": "ES2022" to "target": "ES2021"

Any ideas how to fix it without changing "ES2022" to "ES2021"?

P.S. I need to keep testField and generate as static

Joe Kappa
  • 39
  • 3
  • If you look at the output of the compiler with the target set to [ES 2022](https://www.typescriptlang.org/play?target=9#code/MYGwhgzhAEBiD29oG8BQ1oQC5iwS2GgCMwAnACgEoV0NpSBTLAV1IDtoBmAbloF9atbLgLEwAL2gBeOIgB0JCpVQCgA) vs [ES 2021](https://www.typescriptlang.org/play?target=8#code/MYGwhgzhAEBiD29oG8BQ1oQC5iwS2GgCMwAnACgEoV0NpSBTLAV1IDtoBmAbloF9atbLgLEwAL2gBeOIgB0JCpVQCgA) – Jared Smith Aug 21 '23 at 19:52
  • 1
    ...you will notice that the former makes use of a [static initialization block](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Static_initialization_blocks) which was a new ES 2022 feature whereas the latter just assigns the property to the class object. Are you sure the version of node.js you are using to run your tests supports it? What happens if you fire up a repl and try to evaluate that class definition? – Jared Smith Aug 21 '23 at 19:52
  • My current node version is 18.12.1, I think it should support this feature. Is it possible to restore old behaviour somehow? – Joe Kappa Aug 21 '23 at 20:19
  • It *should*, but if you need to force it instead of declaring the static property just remember TS is a superset of JS: you can always force it by writing out the JS by hand `TestService.testField = ...` the problem is the compiler isn't going to like it. You're going to have to use casts or compiler directives both when you assign it and when you access it in the test. – Jared Smith Aug 21 '23 at 20:39
  • 1
    Thanks for clarifying, I tried to use this static blocks to solve my issue but seems it doesn't work like this: ``static generate(url: string, response: string): string[] { return [url + response]; } static testField; static { this.testField = TestService.generate('', ''); }`` It works: ``static generate(url: string, response: string): string[] { return [url + response]; } static testField: string[]; constructor() { TestService.testField = TestService.generate('', ''); }`` – Joe Kappa Aug 21 '23 at 21:04

0 Answers0